diff options
Diffstat (limited to 'drivers')
93 files changed, 3918 insertions, 1574 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 3c7d8942f23b..b0de6312919a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -903,7 +903,7 @@ static struct acpi_driver acpi_battery_driver = { | |||
903 | }, | 903 | }, |
904 | }; | 904 | }; |
905 | 905 | ||
906 | static void acpi_battery_init_async(void *unused, async_cookie_t cookie) | 906 | static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) |
907 | { | 907 | { |
908 | if (acpi_disabled) | 908 | if (acpi_disabled) |
909 | return; | 909 | return; |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 57be6bea48eb..08186ecbaf8d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -114,6 +114,7 @@ enum { | |||
114 | board_ahci_sb700 = 5, /* for SB700 and SB800 */ | 114 | board_ahci_sb700 = 5, /* for SB700 and SB800 */ |
115 | board_ahci_mcp65 = 6, | 115 | board_ahci_mcp65 = 6, |
116 | board_ahci_nopmp = 7, | 116 | board_ahci_nopmp = 7, |
117 | board_ahci_yesncq = 8, | ||
117 | 118 | ||
118 | /* global controller registers */ | 119 | /* global controller registers */ |
119 | HOST_CAP = 0x00, /* host capabilities */ | 120 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -469,6 +470,14 @@ static const struct ata_port_info ahci_port_info[] = { | |||
469 | .udma_mask = ATA_UDMA6, | 470 | .udma_mask = ATA_UDMA6, |
470 | .port_ops = &ahci_ops, | 471 | .port_ops = &ahci_ops, |
471 | }, | 472 | }, |
473 | /* board_ahci_yesncq */ | ||
474 | { | ||
475 | AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), | ||
476 | .flags = AHCI_FLAG_COMMON, | ||
477 | .pio_mask = ATA_PIO4, | ||
478 | .udma_mask = ATA_UDMA6, | ||
479 | .port_ops = &ahci_ops, | ||
480 | }, | ||
472 | }; | 481 | }; |
473 | 482 | ||
474 | static const struct pci_device_id ahci_pci_tbl[] = { | 483 | static const struct pci_device_id ahci_pci_tbl[] = { |
@@ -535,30 +544,30 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
535 | { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ | 544 | { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ |
536 | { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ | 545 | { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ |
537 | { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ | 546 | { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ |
538 | { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ | 547 | { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq }, /* MCP67 */ |
539 | { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ | 548 | { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq }, /* MCP67 */ |
540 | { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ | 549 | { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq }, /* MCP67 */ |
541 | { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */ | 550 | { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq }, /* MCP67 */ |
542 | { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */ | 551 | { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq }, /* MCP67 */ |
543 | { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */ | 552 | { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq }, /* MCP67 */ |
544 | { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */ | 553 | { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq }, /* MCP67 */ |
545 | { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */ | 554 | { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq }, /* MCP67 */ |
546 | { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */ | 555 | { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq }, /* MCP67 */ |
547 | { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */ | 556 | { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */ |
548 | { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */ | 557 | { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */ |
549 | { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */ | 558 | { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */ |
550 | { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */ | 559 | { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */ |
551 | { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */ | 560 | { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */ |
552 | { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */ | 561 | { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */ |
553 | { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */ | 562 | { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq }, /* MCP73 */ |
554 | { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */ | 563 | { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq }, /* MCP73 */ |
555 | { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */ | 564 | { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq }, /* MCP73 */ |
556 | { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */ | 565 | { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq }, /* MCP73 */ |
557 | { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */ | 566 | { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq }, /* MCP73 */ |
558 | { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */ | 567 | { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq }, /* MCP73 */ |
559 | { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */ | 568 | { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq }, /* MCP73 */ |
560 | { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */ | 569 | { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq }, /* MCP73 */ |
561 | { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */ | 570 | { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq }, /* MCP73 */ |
562 | { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */ | 571 | { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */ |
563 | { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */ | 572 | { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */ |
564 | { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */ | 573 | { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e7ea77cf6069..065507c46644 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -6110,13 +6110,11 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
6110 | ata_port_printk(ap, KERN_INFO, "DUMMY\n"); | 6110 | ata_port_printk(ap, KERN_INFO, "DUMMY\n"); |
6111 | } | 6111 | } |
6112 | 6112 | ||
6113 | /* perform each probe synchronously */ | 6113 | /* perform each probe asynchronously */ |
6114 | DPRINTK("probe begin\n"); | ||
6115 | for (i = 0; i < host->n_ports; i++) { | 6114 | for (i = 0; i < host->n_ports; i++) { |
6116 | struct ata_port *ap = host->ports[i]; | 6115 | struct ata_port *ap = host->ports[i]; |
6117 | async_schedule(async_port_probe, ap); | 6116 | async_schedule(async_port_probe, ap); |
6118 | } | 6117 | } |
6119 | DPRINTK("probe end\n"); | ||
6120 | 6118 | ||
6121 | return 0; | 6119 | return 0; |
6122 | } | 6120 | } |
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 98e8c50703b3..bdd43c7f432e 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -566,7 +566,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
566 | static int printed_version; | 566 | static int printed_version; |
567 | unsigned int i; | 567 | unsigned int i; |
568 | int rc; | 568 | int rc; |
569 | struct ata_host *host; | 569 | struct ata_host *host = NULL; |
570 | int board_id = (int) ent->driver_data; | 570 | int board_id = (int) ent->driver_data; |
571 | const unsigned *bar_sizes; | 571 | const unsigned *bar_sizes; |
572 | 572 | ||
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 6cccdc3f5220..4aecf5dc6a93 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -563,7 +563,7 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
563 | case ACE_FSM_STATE_IDENTIFY_PREPARE: | 563 | case ACE_FSM_STATE_IDENTIFY_PREPARE: |
564 | /* Send identify command */ | 564 | /* Send identify command */ |
565 | ace->fsm_task = ACE_TASK_IDENTIFY; | 565 | ace->fsm_task = ACE_TASK_IDENTIFY; |
566 | ace->data_ptr = &ace->cf_id; | 566 | ace->data_ptr = ace->cf_id; |
567 | ace->data_count = ACE_BUF_PER_SECTOR; | 567 | ace->data_count = ACE_BUF_PER_SECTOR; |
568 | ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY); | 568 | ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY); |
569 | 569 | ||
@@ -608,8 +608,8 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
608 | break; | 608 | break; |
609 | 609 | ||
610 | case ACE_FSM_STATE_IDENTIFY_COMPLETE: | 610 | case ACE_FSM_STATE_IDENTIFY_COMPLETE: |
611 | ace_fix_driveid(&ace->cf_id[0]); | 611 | ace_fix_driveid(ace->cf_id); |
612 | ace_dump_mem(&ace->cf_id, 512); /* Debug: Dump out disk ID */ | 612 | ace_dump_mem(ace->cf_id, 512); /* Debug: Dump out disk ID */ |
613 | 613 | ||
614 | if (ace->data_result) { | 614 | if (ace->data_result) { |
615 | /* Error occured, disable the disk */ | 615 | /* Error occured, disable the disk */ |
@@ -622,9 +622,9 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
622 | 622 | ||
623 | /* Record disk parameters */ | 623 | /* Record disk parameters */ |
624 | set_capacity(ace->gd, | 624 | set_capacity(ace->gd, |
625 | ata_id_u32(&ace->cf_id, ATA_ID_LBA_CAPACITY)); | 625 | ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY)); |
626 | dev_info(ace->dev, "capacity: %i sectors\n", | 626 | dev_info(ace->dev, "capacity: %i sectors\n", |
627 | ata_id_u32(&ace->cf_id, ATA_ID_LBA_CAPACITY)); | 627 | ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY)); |
628 | } | 628 | } |
629 | 629 | ||
630 | /* We're done, drop to IDLE state and notify waiters */ | 630 | /* We're done, drop to IDLE state and notify waiters */ |
@@ -923,7 +923,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode) | |||
923 | static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 923 | static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
924 | { | 924 | { |
925 | struct ace_device *ace = bdev->bd_disk->private_data; | 925 | struct ace_device *ace = bdev->bd_disk->private_data; |
926 | u16 *cf_id = &ace->cf_id[0]; | 926 | u16 *cf_id = ace->cf_id; |
927 | 927 | ||
928 | dev_dbg(ace->dev, "ace_getgeo()\n"); | 928 | dev_dbg(ace->dev, "ace_getgeo()\n"); |
929 | 929 | ||
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index f68e5f8e23ee..6318f7ddc1d4 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c | |||
@@ -190,7 +190,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, | |||
190 | int completed = 1; | 190 | int completed = 1; |
191 | unsigned long timeout = jiffies + i2c_adap->timeout; | 191 | unsigned long timeout = jiffies + i2c_adap->timeout; |
192 | 192 | ||
193 | while (pca_status(adap) != 0xf8) { | 193 | while ((state = pca_status(adap)) != 0xf8) { |
194 | if (time_before(jiffies, timeout)) { | 194 | if (time_before(jiffies, timeout)) { |
195 | msleep(10); | 195 | msleep(10); |
196 | } else { | 196 | } else { |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 94eae5c3cbc7..a48c8aee0218 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -604,12 +604,14 @@ comment "Graphics adapter I2C/DDC channel drivers" | |||
604 | depends on PCI | 604 | depends on PCI |
605 | 605 | ||
606 | config I2C_VOODOO3 | 606 | config I2C_VOODOO3 |
607 | tristate "Voodoo 3" | 607 | tristate "Voodoo 3 (DEPRECATED)" |
608 | depends on PCI | 608 | depends on PCI |
609 | select I2C_ALGOBIT | 609 | select I2C_ALGOBIT |
610 | help | 610 | help |
611 | If you say yes to this option, support will be included for the | 611 | If you say yes to this option, support will be included for the |
612 | Voodoo 3 I2C interface. | 612 | Voodoo 3 I2C interface. This driver is deprecated and you should |
613 | use the tdfxfb driver instead, which additionally provides | ||
614 | framebuffer support. | ||
613 | 615 | ||
614 | This driver can also be built as a module. If so, the module | 616 | This driver can also be built as a module. If so, the module |
615 | will be called i2c-voodoo3. | 617 | will be called i2c-voodoo3. |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b6f3a0de6ca2..85e2e919d1cd 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -716,8 +716,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
716 | 716 | ||
717 | /* new style driver methods can't mix with legacy ones */ | 717 | /* new style driver methods can't mix with legacy ones */ |
718 | if (is_newstyle_driver(driver)) { | 718 | if (is_newstyle_driver(driver)) { |
719 | if (driver->attach_adapter || driver->detach_adapter | 719 | if (driver->detach_adapter || driver->detach_client) { |
720 | || driver->detach_client) { | ||
721 | printk(KERN_WARNING | 720 | printk(KERN_WARNING |
722 | "i2c-core: driver [%s] is confused\n", | 721 | "i2c-core: driver [%s] is confused\n", |
723 | driver->driver.name); | 722 | driver->driver.name); |
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c index 8eda552326e9..403d0e4265db 100644 --- a/drivers/ide/at91_ide.c +++ b/drivers/ide/at91_ide.c | |||
@@ -20,7 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
@@ -175,90 +174,6 @@ static void at91_ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, | |||
175 | leave_16bit(chipselect, mode); | 174 | leave_16bit(chipselect, mode); |
176 | } | 175 | } |
177 | 176 | ||
178 | static u8 ide_mm_inb(unsigned long port) | ||
179 | { | ||
180 | return readb((void __iomem *) port); | ||
181 | } | ||
182 | |||
183 | static void ide_mm_outb(u8 value, unsigned long port) | ||
184 | { | ||
185 | writeb(value, (void __iomem *) port); | ||
186 | } | ||
187 | |||
188 | static void at91_ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | ||
189 | { | ||
190 | ide_hwif_t *hwif = drive->hwif; | ||
191 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
192 | struct ide_taskfile *tf = &cmd->tf; | ||
193 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
194 | |||
195 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | ||
196 | HIHI = 0xFF; | ||
197 | |||
198 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
199 | ide_mm_outb(tf->hob_feature, io_ports->feature_addr); | ||
200 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
201 | ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
202 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
203 | ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
204 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
205 | ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
206 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
207 | ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
208 | |||
209 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
210 | ide_mm_outb(tf->feature, io_ports->feature_addr); | ||
211 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
212 | ide_mm_outb(tf->nsect, io_ports->nsect_addr); | ||
213 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
214 | ide_mm_outb(tf->lbal, io_ports->lbal_addr); | ||
215 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
216 | ide_mm_outb(tf->lbam, io_ports->lbam_addr); | ||
217 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
218 | ide_mm_outb(tf->lbah, io_ports->lbah_addr); | ||
219 | |||
220 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
221 | ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); | ||
222 | } | ||
223 | |||
224 | static void at91_ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | ||
225 | { | ||
226 | ide_hwif_t *hwif = drive->hwif; | ||
227 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
228 | struct ide_taskfile *tf = &cmd->tf; | ||
229 | |||
230 | /* be sure we're looking at the low order bits */ | ||
231 | ide_mm_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
232 | |||
233 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | ||
234 | tf->error = ide_mm_inb(io_ports->feature_addr); | ||
235 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | ||
236 | tf->nsect = ide_mm_inb(io_ports->nsect_addr); | ||
237 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | ||
238 | tf->lbal = ide_mm_inb(io_ports->lbal_addr); | ||
239 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | ||
240 | tf->lbam = ide_mm_inb(io_ports->lbam_addr); | ||
241 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | ||
242 | tf->lbah = ide_mm_inb(io_ports->lbah_addr); | ||
243 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
244 | tf->device = ide_mm_inb(io_ports->device_addr); | ||
245 | |||
246 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
247 | ide_mm_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
248 | |||
249 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
250 | tf->hob_error = ide_mm_inb(io_ports->feature_addr); | ||
251 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
252 | tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); | ||
253 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
254 | tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); | ||
255 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
256 | tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); | ||
257 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
258 | tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) | 177 | static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) |
263 | { | 178 | { |
264 | struct ide_timing *timing; | 179 | struct ide_timing *timing; |
@@ -284,8 +199,8 @@ static const struct ide_tp_ops at91_ide_tp_ops = { | |||
284 | .write_devctl = ide_write_devctl, | 199 | .write_devctl = ide_write_devctl, |
285 | 200 | ||
286 | .dev_select = ide_dev_select, | 201 | .dev_select = ide_dev_select, |
287 | .tf_load = at91_ide_tf_load, | 202 | .tf_load = ide_tf_load, |
288 | .tf_read = at91_ide_tf_read, | 203 | .tf_read = ide_tf_read, |
289 | 204 | ||
290 | .input_data = at91_ide_input_data, | 205 | .input_data = at91_ide_input_data, |
291 | .output_data = at91_ide_output_data, | 206 | .output_data = at91_ide_output_data, |
@@ -300,7 +215,7 @@ static const struct ide_port_info at91_ide_port_info __initdata = { | |||
300 | .tp_ops = &at91_ide_tp_ops, | 215 | .tp_ops = &at91_ide_tp_ops, |
301 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | | 216 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | |
302 | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, | 217 | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, |
303 | .pio_mask = ATA_PIO5, | 218 | .pio_mask = ATA_PIO6, |
304 | }; | 219 | }; |
305 | 220 | ||
306 | /* | 221 | /* |
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c index afa2af9a362b..0e2df6755ec9 100644 --- a/drivers/ide/falconide.c +++ b/drivers/ide/falconide.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/atarihw.h> | 20 | #include <asm/atarihw.h> |
21 | #include <asm/atariints.h> | 21 | #include <asm/atariints.h> |
22 | #include <asm/atari_stdma.h> | 22 | #include <asm/atari_stdma.h> |
23 | #include <asm/ide.h> | ||
23 | 24 | ||
24 | #define DRV_NAME "falconide" | 25 | #define DRV_NAME "falconide" |
25 | 26 | ||
@@ -67,8 +68,10 @@ static void falconide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, | |||
67 | { | 68 | { |
68 | unsigned long data_addr = drive->hwif->io_ports.data_addr; | 69 | unsigned long data_addr = drive->hwif->io_ports.data_addr; |
69 | 70 | ||
70 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) | 71 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) { |
71 | return insw(data_addr, buf, (len + 1) / 2); | 72 | __ide_mm_insw(data_addr, buf, (len + 1) / 2); |
73 | return; | ||
74 | } | ||
72 | 75 | ||
73 | raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2); | 76 | raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2); |
74 | } | 77 | } |
@@ -78,8 +81,10 @@ static void falconide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, | |||
78 | { | 81 | { |
79 | unsigned long data_addr = drive->hwif->io_ports.data_addr; | 82 | unsigned long data_addr = drive->hwif->io_ports.data_addr; |
80 | 83 | ||
81 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) | 84 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) { |
82 | return outsw(data_addr, buf, (len + 1) / 2); | 85 | __ide_mm_outsw(data_addr, buf, (len + 1) / 2); |
86 | return; | ||
87 | } | ||
83 | 88 | ||
84 | raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2); | 89 | raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2); |
85 | } | 90 | } |
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 12f436951bff..77f79d26b264 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
@@ -318,8 +318,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, | |||
318 | 318 | ||
319 | /* convert GTF to taskfile */ | 319 | /* convert GTF to taskfile */ |
320 | memset(&cmd, 0, sizeof(cmd)); | 320 | memset(&cmd, 0, sizeof(cmd)); |
321 | memcpy(&cmd.tf_array[7], gtf, REGS_PER_GTF); | 321 | memcpy(&cmd.tf.feature, gtf, REGS_PER_GTF); |
322 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 322 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
323 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
323 | 324 | ||
324 | err = ide_no_data_taskfile(drive, &cmd); | 325 | err = ide_no_data_taskfile(drive, &cmd); |
325 | if (err) { | 326 | if (err) { |
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3e43b889dd64..7201b176d75b 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -254,16 +254,13 @@ EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); | |||
254 | 254 | ||
255 | void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) | 255 | void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) |
256 | { | 256 | { |
257 | struct ide_cmd cmd; | 257 | struct ide_taskfile tf; |
258 | 258 | ||
259 | memset(&cmd, 0, sizeof(cmd)); | 259 | drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT | |
260 | cmd.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | | 260 | IDE_VALID_LBAM | IDE_VALID_LBAH); |
261 | IDE_TFLAG_IN_NSECT; | ||
262 | 261 | ||
263 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 262 | *bcount = (tf.lbah << 8) | tf.lbam; |
264 | 263 | *ireason = tf.nsect & 3; | |
265 | *bcount = (cmd.tf.lbah << 8) | cmd.tf.lbam; | ||
266 | *ireason = cmd.tf.nsect & 3; | ||
267 | } | 264 | } |
268 | EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); | 265 | EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); |
269 | 266 | ||
@@ -439,12 +436,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
439 | return ide_started; | 436 | return ide_started; |
440 | } | 437 | } |
441 | 438 | ||
442 | static void ide_init_packet_cmd(struct ide_cmd *cmd, u32 tf_flags, | 439 | static void ide_init_packet_cmd(struct ide_cmd *cmd, u8 valid_tf, |
443 | u16 bcount, u8 dma) | 440 | u16 bcount, u8 dma) |
444 | { | 441 | { |
445 | cmd->protocol = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO; | 442 | cmd->protocol = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO; |
446 | cmd->tf_flags |= IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | | 443 | cmd->valid.out.tf = IDE_VALID_LBAH | IDE_VALID_LBAM | |
447 | IDE_TFLAG_OUT_FEATURE | tf_flags; | 444 | IDE_VALID_FEATURE | valid_tf; |
448 | cmd->tf.command = ATA_CMD_PACKET; | 445 | cmd->tf.command = ATA_CMD_PACKET; |
449 | cmd->tf.feature = dma; /* Use PIO/DMA */ | 446 | cmd->tf.feature = dma; /* Use PIO/DMA */ |
450 | cmd->tf.lbam = bcount & 0xff; | 447 | cmd->tf.lbam = bcount & 0xff; |
@@ -453,14 +450,11 @@ static void ide_init_packet_cmd(struct ide_cmd *cmd, u32 tf_flags, | |||
453 | 450 | ||
454 | static u8 ide_read_ireason(ide_drive_t *drive) | 451 | static u8 ide_read_ireason(ide_drive_t *drive) |
455 | { | 452 | { |
456 | struct ide_cmd cmd; | 453 | struct ide_taskfile tf; |
457 | |||
458 | memset(&cmd, 0, sizeof(cmd)); | ||
459 | cmd.tf_flags = IDE_TFLAG_IN_NSECT; | ||
460 | 454 | ||
461 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 455 | drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT); |
462 | 456 | ||
463 | return cmd.tf.nsect & 3; | 457 | return tf.nsect & 3; |
464 | } | 458 | } |
465 | 459 | ||
466 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | 460 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) |
@@ -588,12 +582,12 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
588 | ide_expiry_t *expiry = NULL; | 582 | ide_expiry_t *expiry = NULL; |
589 | struct request *rq = hwif->rq; | 583 | struct request *rq = hwif->rq; |
590 | unsigned int timeout; | 584 | unsigned int timeout; |
591 | u32 tf_flags; | ||
592 | u16 bcount; | 585 | u16 bcount; |
586 | u8 valid_tf; | ||
593 | u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT); | 587 | u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT); |
594 | 588 | ||
595 | if (dev_is_idecd(drive)) { | 589 | if (dev_is_idecd(drive)) { |
596 | tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; | 590 | valid_tf = IDE_VALID_NSECT | IDE_VALID_LBAL; |
597 | bcount = ide_cd_get_xferlen(rq); | 591 | bcount = ide_cd_get_xferlen(rq); |
598 | expiry = ide_cd_expiry; | 592 | expiry = ide_cd_expiry; |
599 | timeout = ATAPI_WAIT_PC; | 593 | timeout = ATAPI_WAIT_PC; |
@@ -607,7 +601,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
607 | pc->xferred = 0; | 601 | pc->xferred = 0; |
608 | pc->cur_pos = pc->buf; | 602 | pc->cur_pos = pc->buf; |
609 | 603 | ||
610 | tf_flags = IDE_TFLAG_OUT_DEVICE; | 604 | valid_tf = IDE_VALID_DEVICE; |
611 | bcount = ((drive->media == ide_tape) ? | 605 | bcount = ((drive->media == ide_tape) ? |
612 | pc->req_xfer : | 606 | pc->req_xfer : |
613 | min(pc->req_xfer, 63 * 1024)); | 607 | min(pc->req_xfer, 63 * 1024)); |
@@ -627,7 +621,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
627 | : WAIT_TAPE_CMD; | 621 | : WAIT_TAPE_CMD; |
628 | } | 622 | } |
629 | 623 | ||
630 | ide_init_packet_cmd(cmd, tf_flags, bcount, drive->dma); | 624 | ide_init_packet_cmd(cmd, valid_tf, bcount, drive->dma); |
631 | 625 | ||
632 | (void)do_rw_taskfile(drive, cmd); | 626 | (void)do_rw_taskfile(drive, cmd); |
633 | 627 | ||
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 35729a47f797..3aec19d1fdfc 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -265,35 +265,62 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) | |||
265 | cdrom_analyze_sense_data(drive, NULL, sense); | 265 | cdrom_analyze_sense_data(drive, NULL, sense); |
266 | } | 266 | } |
267 | 267 | ||
268 | |||
268 | /* | 269 | /* |
270 | * Allow the drive 5 seconds to recover; some devices will return NOT_READY | ||
271 | * while flushing data from cache. | ||
272 | * | ||
273 | * returns: 0 failed (write timeout expired) | ||
274 | * 1 success | ||
275 | */ | ||
276 | static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) | ||
277 | { | ||
278 | |||
279 | struct cdrom_info *info = drive->driver_data; | ||
280 | |||
281 | if (!rq->errors) | ||
282 | info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; | ||
283 | |||
284 | rq->errors = 1; | ||
285 | |||
286 | if (time_after(jiffies, info->write_timeout)) | ||
287 | return 0; | ||
288 | else { | ||
289 | struct request_queue *q = drive->queue; | ||
290 | unsigned long flags; | ||
291 | |||
292 | /* | ||
293 | * take a breather relying on the unplug timer to kick us again | ||
294 | */ | ||
295 | |||
296 | spin_lock_irqsave(q->queue_lock, flags); | ||
297 | blk_plug_device(q); | ||
298 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
299 | |||
300 | return 1; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | /** | ||
269 | * Returns: | 305 | * Returns: |
270 | * 0: if the request should be continued. | 306 | * 0: if the request should be continued. |
271 | * 1: if the request will be going through error recovery. | 307 | * 1: if the request will be going through error recovery. |
272 | * 2: if the request should be ended. | 308 | * 2: if the request should be ended. |
273 | */ | 309 | */ |
274 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 310 | static int cdrom_decode_status(ide_drive_t *drive, u8 stat) |
275 | { | 311 | { |
276 | ide_hwif_t *hwif = drive->hwif; | 312 | ide_hwif_t *hwif = drive->hwif; |
277 | struct request *rq = hwif->rq; | 313 | struct request *rq = hwif->rq; |
278 | int stat, err, sense_key; | 314 | int err, sense_key, do_end_request = 0; |
279 | 315 | u8 quiet = rq->cmd_flags & REQ_QUIET; | |
280 | /* check for errors */ | ||
281 | stat = hwif->tp_ops->read_status(hwif); | ||
282 | |||
283 | if (stat_ret) | ||
284 | *stat_ret = stat; | ||
285 | |||
286 | if (OK_STAT(stat, good_stat, BAD_R_STAT)) | ||
287 | return 0; | ||
288 | 316 | ||
289 | /* get the IDE error register */ | 317 | /* get the IDE error register */ |
290 | err = ide_read_error(drive); | 318 | err = ide_read_error(drive); |
291 | sense_key = err >> 4; | 319 | sense_key = err >> 4; |
292 | 320 | ||
293 | ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, " | 321 | ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, rq->cmd_type: 0x%x, err: 0x%x, " |
294 | "rq->cmd_type: 0x%x, err: 0x%x", | 322 | "stat 0x%x", |
295 | stat, good_stat, rq->cmd[0], rq->cmd_type, | 323 | rq->cmd[0], rq->cmd_type, err, stat); |
296 | err); | ||
297 | 324 | ||
298 | if (blk_sense_request(rq)) { | 325 | if (blk_sense_request(rq)) { |
299 | /* | 326 | /* |
@@ -303,151 +330,108 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
303 | */ | 330 | */ |
304 | rq->cmd_flags |= REQ_FAILED; | 331 | rq->cmd_flags |= REQ_FAILED; |
305 | return 2; | 332 | return 2; |
306 | } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { | 333 | } |
307 | /* All other functions, except for READ. */ | ||
308 | 334 | ||
309 | /* | 335 | /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */ |
310 | * if we have an error, pass back CHECK_CONDITION as the | 336 | if (blk_pc_request(rq) && !rq->errors) |
311 | * scsi status byte | 337 | rq->errors = SAM_STAT_CHECK_CONDITION; |
312 | */ | ||
313 | if (blk_pc_request(rq) && !rq->errors) | ||
314 | rq->errors = SAM_STAT_CHECK_CONDITION; | ||
315 | 338 | ||
316 | /* check for tray open */ | 339 | if (blk_noretry_request(rq)) |
317 | if (sense_key == NOT_READY) { | 340 | do_end_request = 1; |
318 | cdrom_saw_media_change(drive); | 341 | |
319 | } else if (sense_key == UNIT_ATTENTION) { | 342 | switch (sense_key) { |
320 | /* check for media change */ | 343 | case NOT_READY: |
344 | if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) { | ||
345 | if (ide_cd_breathe(drive, rq)) | ||
346 | return 1; | ||
347 | } else { | ||
321 | cdrom_saw_media_change(drive); | 348 | cdrom_saw_media_change(drive); |
322 | return 0; | 349 | |
323 | } else if (sense_key == ILLEGAL_REQUEST && | 350 | if (blk_fs_request(rq) && !quiet) |
324 | rq->cmd[0] == GPCMD_START_STOP_UNIT) { | 351 | printk(KERN_ERR PFX "%s: tray open\n", |
325 | /* | 352 | drive->name); |
326 | * Don't print error message for this condition-- | ||
327 | * SFF8090i indicates that 5/24/00 is the correct | ||
328 | * response to a request to close the tray if the | ||
329 | * drive doesn't have that capability. | ||
330 | * cdrom_log_sense() knows this! | ||
331 | */ | ||
332 | } else if (!(rq->cmd_flags & REQ_QUIET)) { | ||
333 | /* otherwise, print an error */ | ||
334 | ide_dump_status(drive, "packet command error", stat); | ||
335 | } | 353 | } |
354 | do_end_request = 1; | ||
355 | break; | ||
356 | case UNIT_ATTENTION: | ||
357 | cdrom_saw_media_change(drive); | ||
336 | 358 | ||
337 | rq->cmd_flags |= REQ_FAILED; | 359 | if (blk_fs_request(rq) == 0) |
360 | return 0; | ||
338 | 361 | ||
339 | /* | 362 | /* |
340 | * instead of playing games with moving completions around, | 363 | * Arrange to retry the request but be sure to give up if we've |
341 | * remove failed request completely and end it when the | 364 | * retried too many times. |
342 | * request sense has completed | ||
343 | */ | 365 | */ |
344 | goto end_request; | 366 | if (++rq->errors > ERROR_MAX) |
345 | |||
346 | } else if (blk_fs_request(rq)) { | ||
347 | int do_end_request = 0; | ||
348 | |||
349 | /* handle errors from READ and WRITE requests */ | ||
350 | |||
351 | if (blk_noretry_request(rq)) | ||
352 | do_end_request = 1; | 367 | do_end_request = 1; |
353 | 368 | break; | |
354 | if (sense_key == NOT_READY) { | 369 | case ILLEGAL_REQUEST: |
355 | /* tray open */ | 370 | /* |
356 | if (rq_data_dir(rq) == READ) { | 371 | * Don't print error message for this condition -- SFF8090i |
357 | cdrom_saw_media_change(drive); | 372 | * indicates that 5/24/00 is the correct response to a request |
358 | 373 | * to close the tray if the drive doesn't have that capability. | |
359 | /* fail the request */ | 374 | * |
360 | printk(KERN_ERR PFX "%s: tray open\n", | 375 | * cdrom_log_sense() knows this! |
361 | drive->name); | 376 | */ |
362 | do_end_request = 1; | 377 | if (rq->cmd[0] == GPCMD_START_STOP_UNIT) |
363 | } else { | 378 | break; |
364 | struct cdrom_info *info = drive->driver_data; | 379 | /* fall-through */ |
365 | 380 | case DATA_PROTECT: | |
366 | /* | 381 | /* |
367 | * Allow the drive 5 seconds to recover, some | 382 | * No point in retrying after an illegal request or data |
368 | * devices will return this error while flushing | 383 | * protect error. |
369 | * data from cache. | 384 | */ |
370 | */ | 385 | if (!quiet) |
371 | if (!rq->errors) | ||
372 | info->write_timeout = jiffies + | ||
373 | ATAPI_WAIT_WRITE_BUSY; | ||
374 | rq->errors = 1; | ||
375 | if (time_after(jiffies, info->write_timeout)) | ||
376 | do_end_request = 1; | ||
377 | else { | ||
378 | struct request_queue *q = drive->queue; | ||
379 | unsigned long flags; | ||
380 | |||
381 | /* | ||
382 | * take a breather relying on the unplug | ||
383 | * timer to kick us again | ||
384 | */ | ||
385 | spin_lock_irqsave(q->queue_lock, flags); | ||
386 | blk_plug_device(q); | ||
387 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
388 | |||
389 | return 1; | ||
390 | } | ||
391 | } | ||
392 | } else if (sense_key == UNIT_ATTENTION) { | ||
393 | /* media change */ | ||
394 | cdrom_saw_media_change(drive); | ||
395 | |||
396 | /* | ||
397 | * Arrange to retry the request but be sure to give up | ||
398 | * if we've retried too many times. | ||
399 | */ | ||
400 | if (++rq->errors > ERROR_MAX) | ||
401 | do_end_request = 1; | ||
402 | } else if (sense_key == ILLEGAL_REQUEST || | ||
403 | sense_key == DATA_PROTECT) { | ||
404 | /* | ||
405 | * No point in retrying after an illegal request or data | ||
406 | * protect error. | ||
407 | */ | ||
408 | ide_dump_status(drive, "command error", stat); | 386 | ide_dump_status(drive, "command error", stat); |
409 | do_end_request = 1; | 387 | do_end_request = 1; |
410 | } else if (sense_key == MEDIUM_ERROR) { | 388 | break; |
411 | /* | 389 | case MEDIUM_ERROR: |
412 | * No point in re-trying a zillion times on a bad | 390 | /* |
413 | * sector. If we got here the error is not correctable. | 391 | * No point in re-trying a zillion times on a bad sector. |
414 | */ | 392 | * If we got here the error is not correctable. |
415 | ide_dump_status(drive, "media error (bad sector)", | 393 | */ |
394 | if (!quiet) | ||
395 | ide_dump_status(drive, "media error " | ||
396 | "(bad sector)", stat); | ||
397 | do_end_request = 1; | ||
398 | break; | ||
399 | case BLANK_CHECK: | ||
400 | /* disk appears blank? */ | ||
401 | if (!quiet) | ||
402 | ide_dump_status(drive, "media error (blank)", | ||
416 | stat); | 403 | stat); |
417 | do_end_request = 1; | 404 | do_end_request = 1; |
418 | } else if (sense_key == BLANK_CHECK) { | 405 | break; |
419 | /* disk appears blank ?? */ | 406 | default: |
420 | ide_dump_status(drive, "media error (blank)", stat); | 407 | if (blk_fs_request(rq) == 0) |
421 | do_end_request = 1; | 408 | break; |
422 | } else if ((err & ~ATA_ABORTED) != 0) { | 409 | if (err & ~ATA_ABORTED) { |
423 | /* go to the default handler for other errors */ | 410 | /* go to the default handler for other errors */ |
424 | ide_error(drive, "cdrom_decode_status", stat); | 411 | ide_error(drive, "cdrom_decode_status", stat); |
425 | return 1; | 412 | return 1; |
426 | } else if ((++rq->errors > ERROR_MAX)) { | 413 | } else if (++rq->errors > ERROR_MAX) |
427 | /* we've racked up too many retries, abort */ | 414 | /* we've racked up too many retries, abort */ |
428 | do_end_request = 1; | 415 | do_end_request = 1; |
429 | } | 416 | } |
430 | |||
431 | /* | ||
432 | * End a request through request sense analysis when we have | ||
433 | * sense data. We need this in order to perform end of media | ||
434 | * processing. | ||
435 | */ | ||
436 | if (do_end_request) | ||
437 | goto end_request; | ||
438 | 417 | ||
439 | /* | 418 | if (blk_fs_request(rq) == 0) { |
440 | * If we got a CHECK_CONDITION status, queue | 419 | rq->cmd_flags |= REQ_FAILED; |
441 | * a request sense command. | 420 | do_end_request = 1; |
442 | */ | ||
443 | if (stat & ATA_ERR) | ||
444 | cdrom_queue_request_sense(drive, NULL, NULL); | ||
445 | return 1; | ||
446 | } else { | ||
447 | blk_dump_rq_flags(rq, PFX "bad rq"); | ||
448 | return 2; | ||
449 | } | 421 | } |
450 | 422 | ||
423 | /* | ||
424 | * End a request through request sense analysis when we have sense data. | ||
425 | * We need this in order to perform end of media processing. | ||
426 | */ | ||
427 | if (do_end_request) | ||
428 | goto end_request; | ||
429 | |||
430 | /* if we got a CHECK_CONDITION status, queue a request sense command */ | ||
431 | if (stat & ATA_ERR) | ||
432 | cdrom_queue_request_sense(drive, NULL, NULL); | ||
433 | return 1; | ||
434 | |||
451 | end_request: | 435 | end_request: |
452 | if (stat & ATA_ERR) { | 436 | if (stat & ATA_ERR) { |
453 | struct request_queue *q = drive->queue; | 437 | struct request_queue *q = drive->queue; |
@@ -624,15 +608,14 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
624 | struct ide_cmd *cmd = &hwif->cmd; | 608 | struct ide_cmd *cmd = &hwif->cmd; |
625 | struct request *rq = hwif->rq; | 609 | struct request *rq = hwif->rq; |
626 | ide_expiry_t *expiry = NULL; | 610 | ide_expiry_t *expiry = NULL; |
627 | int dma_error = 0, dma, stat, thislen, uptodate = 0; | 611 | int dma_error = 0, dma, thislen, uptodate = 0; |
628 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors; | 612 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors; |
629 | int sense = blk_sense_request(rq); | 613 | int sense = blk_sense_request(rq); |
630 | unsigned int timeout; | 614 | unsigned int timeout; |
631 | u16 len; | 615 | u16 len; |
632 | u8 ireason; | 616 | u8 ireason, stat; |
633 | 617 | ||
634 | ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x", | 618 | ide_debug_log(IDE_DBG_PC, "cmd: 0x%x, write: 0x%x", rq->cmd[0], write); |
635 | rq->cmd[0], write); | ||
636 | 619 | ||
637 | /* check for errors */ | 620 | /* check for errors */ |
638 | dma = drive->dma; | 621 | dma = drive->dma; |
@@ -648,11 +631,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
648 | } | 631 | } |
649 | } | 632 | } |
650 | 633 | ||
651 | rc = cdrom_decode_status(drive, 0, &stat); | 634 | /* check status */ |
652 | if (rc) { | 635 | stat = hwif->tp_ops->read_status(hwif); |
653 | if (rc == 2) | 636 | |
654 | goto out_end; | 637 | if (!OK_STAT(stat, 0, BAD_R_STAT)) { |
655 | return ide_stopped; | 638 | rc = cdrom_decode_status(drive, stat); |
639 | if (rc) { | ||
640 | if (rc == 2) | ||
641 | goto out_end; | ||
642 | return ide_stopped; | ||
643 | } | ||
656 | } | 644 | } |
657 | 645 | ||
658 | /* using dma, transfer is complete now */ | 646 | /* using dma, transfer is complete now */ |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index c998cf8e971a..a9fbe2c31210 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -97,35 +97,38 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
97 | } | 97 | } |
98 | 98 | ||
99 | memset(&cmd, 0, sizeof(cmd)); | 99 | memset(&cmd, 0, sizeof(cmd)); |
100 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 100 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
101 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
101 | 102 | ||
102 | if (drive->dev_flags & IDE_DFLAG_LBA) { | 103 | if (drive->dev_flags & IDE_DFLAG_LBA) { |
103 | if (lba48) { | 104 | if (lba48) { |
104 | pr_debug("%s: LBA=0x%012llx\n", drive->name, | 105 | pr_debug("%s: LBA=0x%012llx\n", drive->name, |
105 | (unsigned long long)block); | 106 | (unsigned long long)block); |
106 | 107 | ||
107 | tf->hob_nsect = (nsectors >> 8) & 0xff; | ||
108 | tf->hob_lbal = (u8)(block >> 24); | ||
109 | if (sizeof(block) != 4) { | ||
110 | tf->hob_lbam = (u8)((u64)block >> 32); | ||
111 | tf->hob_lbah = (u8)((u64)block >> 40); | ||
112 | } | ||
113 | |||
114 | tf->nsect = nsectors & 0xff; | 108 | tf->nsect = nsectors & 0xff; |
115 | tf->lbal = (u8) block; | 109 | tf->lbal = (u8) block; |
116 | tf->lbam = (u8)(block >> 8); | 110 | tf->lbam = (u8)(block >> 8); |
117 | tf->lbah = (u8)(block >> 16); | 111 | tf->lbah = (u8)(block >> 16); |
112 | tf->device = ATA_LBA; | ||
118 | 113 | ||
119 | cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); | 114 | tf = &cmd.hob; |
115 | tf->nsect = (nsectors >> 8) & 0xff; | ||
116 | tf->lbal = (u8)(block >> 24); | ||
117 | if (sizeof(block) != 4) { | ||
118 | tf->lbam = (u8)((u64)block >> 32); | ||
119 | tf->lbah = (u8)((u64)block >> 40); | ||
120 | } | ||
121 | |||
122 | cmd.valid.out.hob = IDE_VALID_OUT_HOB; | ||
123 | cmd.valid.in.hob = IDE_VALID_IN_HOB; | ||
124 | cmd.tf_flags |= IDE_TFLAG_LBA48; | ||
120 | } else { | 125 | } else { |
121 | tf->nsect = nsectors & 0xff; | 126 | tf->nsect = nsectors & 0xff; |
122 | tf->lbal = block; | 127 | tf->lbal = block; |
123 | tf->lbam = block >>= 8; | 128 | tf->lbam = block >>= 8; |
124 | tf->lbah = block >>= 8; | 129 | tf->lbah = block >>= 8; |
125 | tf->device = (block >> 8) & 0xf; | 130 | tf->device = ((block >> 8) & 0xf) | ATA_LBA; |
126 | } | 131 | } |
127 | |||
128 | tf->device |= ATA_LBA; | ||
129 | } else { | 132 | } else { |
130 | unsigned int sect, head, cyl, track; | 133 | unsigned int sect, head, cyl, track; |
131 | 134 | ||
@@ -220,15 +223,19 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) | |||
220 | tf->command = ATA_CMD_READ_NATIVE_MAX; | 223 | tf->command = ATA_CMD_READ_NATIVE_MAX; |
221 | tf->device = ATA_LBA; | 224 | tf->device = ATA_LBA; |
222 | 225 | ||
223 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 226 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
224 | if (lba48) | 227 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
225 | cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); | 228 | if (lba48) { |
229 | cmd.valid.out.hob = IDE_VALID_OUT_HOB; | ||
230 | cmd.valid.in.hob = IDE_VALID_IN_HOB; | ||
231 | cmd.tf_flags = IDE_TFLAG_LBA48; | ||
232 | } | ||
226 | 233 | ||
227 | ide_no_data_taskfile(drive, &cmd); | 234 | ide_no_data_taskfile(drive, &cmd); |
228 | 235 | ||
229 | /* if OK, compute maximum address value */ | 236 | /* if OK, compute maximum address value */ |
230 | if (!(tf->status & ATA_ERR)) | 237 | if (!(tf->status & ATA_ERR)) |
231 | addr = ide_get_lba_addr(tf, lba48) + 1; | 238 | addr = ide_get_lba_addr(&cmd, lba48) + 1; |
232 | 239 | ||
233 | return addr; | 240 | return addr; |
234 | } | 241 | } |
@@ -250,9 +257,9 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) | |||
250 | tf->lbam = (addr_req >>= 8) & 0xff; | 257 | tf->lbam = (addr_req >>= 8) & 0xff; |
251 | tf->lbah = (addr_req >>= 8) & 0xff; | 258 | tf->lbah = (addr_req >>= 8) & 0xff; |
252 | if (lba48) { | 259 | if (lba48) { |
253 | tf->hob_lbal = (addr_req >>= 8) & 0xff; | 260 | cmd.hob.lbal = (addr_req >>= 8) & 0xff; |
254 | tf->hob_lbam = (addr_req >>= 8) & 0xff; | 261 | cmd.hob.lbam = (addr_req >>= 8) & 0xff; |
255 | tf->hob_lbah = (addr_req >>= 8) & 0xff; | 262 | cmd.hob.lbah = (addr_req >>= 8) & 0xff; |
256 | tf->command = ATA_CMD_SET_MAX_EXT; | 263 | tf->command = ATA_CMD_SET_MAX_EXT; |
257 | } else { | 264 | } else { |
258 | tf->device = (addr_req >>= 8) & 0x0f; | 265 | tf->device = (addr_req >>= 8) & 0x0f; |
@@ -260,15 +267,19 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) | |||
260 | } | 267 | } |
261 | tf->device |= ATA_LBA; | 268 | tf->device |= ATA_LBA; |
262 | 269 | ||
263 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 270 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
264 | if (lba48) | 271 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
265 | cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); | 272 | if (lba48) { |
273 | cmd.valid.out.hob = IDE_VALID_OUT_HOB; | ||
274 | cmd.valid.in.hob = IDE_VALID_IN_HOB; | ||
275 | cmd.tf_flags = IDE_TFLAG_LBA48; | ||
276 | } | ||
266 | 277 | ||
267 | ide_no_data_taskfile(drive, &cmd); | 278 | ide_no_data_taskfile(drive, &cmd); |
268 | 279 | ||
269 | /* if OK, compute maximum address value */ | 280 | /* if OK, compute maximum address value */ |
270 | if (!(tf->status & ATA_ERR)) | 281 | if (!(tf->status & ATA_ERR)) |
271 | addr_set = ide_get_lba_addr(tf, lba48) + 1; | 282 | addr_set = ide_get_lba_addr(&cmd, lba48) + 1; |
272 | 283 | ||
273 | return addr_set; | 284 | return addr_set; |
274 | } | 285 | } |
@@ -395,8 +406,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | |||
395 | cmd->tf.command = ATA_CMD_FLUSH_EXT; | 406 | cmd->tf.command = ATA_CMD_FLUSH_EXT; |
396 | else | 407 | else |
397 | cmd->tf.command = ATA_CMD_FLUSH; | 408 | cmd->tf.command = ATA_CMD_FLUSH; |
398 | cmd->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE | | 409 | cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
399 | IDE_TFLAG_DYN; | 410 | cmd->tf_flags = IDE_TFLAG_DYN; |
400 | cmd->protocol = ATA_PROT_NODATA; | 411 | cmd->protocol = ATA_PROT_NODATA; |
401 | 412 | ||
402 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 413 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
@@ -457,7 +468,8 @@ static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) | |||
457 | cmd.tf.feature = feature; | 468 | cmd.tf.feature = feature; |
458 | cmd.tf.nsect = nsect; | 469 | cmd.tf.nsect = nsect; |
459 | cmd.tf.command = ATA_CMD_SET_FEATURES; | 470 | cmd.tf.command = ATA_CMD_SET_FEATURES; |
460 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 471 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
472 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
461 | 473 | ||
462 | return ide_no_data_taskfile(drive, &cmd); | 474 | return ide_no_data_taskfile(drive, &cmd); |
463 | } | 475 | } |
@@ -533,7 +545,8 @@ static int do_idedisk_flushcache(ide_drive_t *drive) | |||
533 | cmd.tf.command = ATA_CMD_FLUSH_EXT; | 545 | cmd.tf.command = ATA_CMD_FLUSH_EXT; |
534 | else | 546 | else |
535 | cmd.tf.command = ATA_CMD_FLUSH; | 547 | cmd.tf.command = ATA_CMD_FLUSH; |
536 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 548 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
549 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
537 | 550 | ||
538 | return ide_no_data_taskfile(drive, &cmd); | 551 | return ide_no_data_taskfile(drive, &cmd); |
539 | } | 552 | } |
@@ -715,7 +728,8 @@ static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | |||
715 | 728 | ||
716 | memset(&cmd, 0, sizeof(cmd)); | 729 | memset(&cmd, 0, sizeof(cmd)); |
717 | cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; | 730 | cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; |
718 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 731 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
732 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
719 | 733 | ||
720 | ret = ide_no_data_taskfile(drive, &cmd); | 734 | ret = ide_no_data_taskfile(drive, &cmd); |
721 | 735 | ||
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c index eaea3bef2073..19f263bf0a9e 100644 --- a/drivers/ide/ide-disk_proc.c +++ b/drivers/ide/ide-disk_proc.c | |||
@@ -13,7 +13,8 @@ static int smart_enable(ide_drive_t *drive) | |||
13 | tf->lbam = ATA_SMART_LBAM_PASS; | 13 | tf->lbam = ATA_SMART_LBAM_PASS; |
14 | tf->lbah = ATA_SMART_LBAH_PASS; | 14 | tf->lbah = ATA_SMART_LBAH_PASS; |
15 | tf->command = ATA_CMD_SMART; | 15 | tf->command = ATA_CMD_SMART; |
16 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 16 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
17 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
17 | 18 | ||
18 | return ide_no_data_taskfile(drive, &cmd); | 19 | return ide_no_data_taskfile(drive, &cmd); |
19 | } | 20 | } |
@@ -29,7 +30,8 @@ static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) | |||
29 | tf->lbam = ATA_SMART_LBAM_PASS; | 30 | tf->lbam = ATA_SMART_LBAM_PASS; |
30 | tf->lbah = ATA_SMART_LBAH_PASS; | 31 | tf->lbah = ATA_SMART_LBAH_PASS; |
31 | tf->command = ATA_CMD_SMART; | 32 | tf->command = ATA_CMD_SMART; |
32 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 33 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
34 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
33 | cmd.protocol = ATA_PROT_PIO; | 35 | cmd.protocol = ATA_PROT_PIO; |
34 | 36 | ||
35 | return ide_raw_taskfile(drive, &cmd, buf, 1); | 37 | return ide_raw_taskfile(drive, &cmd, buf, 1); |
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c index 16fc46edc32d..e4cdf78cc3e9 100644 --- a/drivers/ide/ide-dma-sff.c +++ b/drivers/ide/ide-dma-sff.c | |||
@@ -277,8 +277,6 @@ void ide_dma_start(ide_drive_t *drive) | |||
277 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 277 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
278 | outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); | 278 | outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); |
279 | } | 279 | } |
280 | |||
281 | wmb(); | ||
282 | } | 280 | } |
283 | EXPORT_SYMBOL_GPL(ide_dma_start); | 281 | EXPORT_SYMBOL_GPL(ide_dma_start); |
284 | 282 | ||
@@ -286,7 +284,7 @@ EXPORT_SYMBOL_GPL(ide_dma_start); | |||
286 | int ide_dma_end(ide_drive_t *drive) | 284 | int ide_dma_end(ide_drive_t *drive) |
287 | { | 285 | { |
288 | ide_hwif_t *hwif = drive->hwif; | 286 | ide_hwif_t *hwif = drive->hwif; |
289 | u8 dma_stat = 0, dma_cmd = 0, mask; | 287 | u8 dma_stat = 0, dma_cmd = 0; |
290 | 288 | ||
291 | /* stop DMA */ | 289 | /* stop DMA */ |
292 | if (hwif->host_flags & IDE_HFLAG_MMIO) { | 290 | if (hwif->host_flags & IDE_HFLAG_MMIO) { |
@@ -304,11 +302,10 @@ int ide_dma_end(ide_drive_t *drive) | |||
304 | /* clear INTR & ERROR bits */ | 302 | /* clear INTR & ERROR bits */ |
305 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); | 303 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); |
306 | 304 | ||
307 | wmb(); | 305 | #define CHECK_DMA_MASK (ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR) |
308 | 306 | ||
309 | /* verify good DMA status */ | 307 | /* verify good DMA status */ |
310 | mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR; | 308 | if ((dma_stat & CHECK_DMA_MASK) != ATA_DMA_INTR) |
311 | if ((dma_stat & mask) != ATA_DMA_INTR) | ||
312 | return 0x10 | dma_stat; | 309 | return 0x10 | dma_stat; |
313 | return 0; | 310 | return 0; |
314 | } | 311 | } |
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c index dac9a6d44963..c06ebdc4a130 100644 --- a/drivers/ide/ide-h8300.c +++ b/drivers/ide/ide-h8300.c | |||
@@ -22,103 +22,6 @@ | |||
22 | (r); \ | 22 | (r); \ |
23 | }) | 23 | }) |
24 | 24 | ||
25 | static void mm_outw(u16 d, unsigned long a) | ||
26 | { | ||
27 | __asm__("mov.b %w0,r2h\n\t" | ||
28 | "mov.b %x0,r2l\n\t" | ||
29 | "mov.w r2,@%1" | ||
30 | : | ||
31 | :"r"(d),"r"(a) | ||
32 | :"er2"); | ||
33 | } | ||
34 | |||
35 | static u16 mm_inw(unsigned long a) | ||
36 | { | ||
37 | register u16 r __asm__("er0"); | ||
38 | __asm__("mov.w @%1,r2\n\t" | ||
39 | "mov.b r2l,%x0\n\t" | ||
40 | "mov.b r2h,%w0" | ||
41 | :"=r"(r) | ||
42 | :"r"(a) | ||
43 | :"er2"); | ||
44 | return r; | ||
45 | } | ||
46 | |||
47 | static void h8300_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | ||
48 | { | ||
49 | ide_hwif_t *hwif = drive->hwif; | ||
50 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
51 | struct ide_taskfile *tf = &cmd->tf; | ||
52 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
53 | |||
54 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | ||
55 | HIHI = 0xFF; | ||
56 | |||
57 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
58 | outb(tf->hob_feature, io_ports->feature_addr); | ||
59 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
60 | outb(tf->hob_nsect, io_ports->nsect_addr); | ||
61 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
62 | outb(tf->hob_lbal, io_ports->lbal_addr); | ||
63 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
64 | outb(tf->hob_lbam, io_ports->lbam_addr); | ||
65 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
66 | outb(tf->hob_lbah, io_ports->lbah_addr); | ||
67 | |||
68 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
69 | outb(tf->feature, io_ports->feature_addr); | ||
70 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
71 | outb(tf->nsect, io_ports->nsect_addr); | ||
72 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
73 | outb(tf->lbal, io_ports->lbal_addr); | ||
74 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
75 | outb(tf->lbam, io_ports->lbam_addr); | ||
76 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
77 | outb(tf->lbah, io_ports->lbah_addr); | ||
78 | |||
79 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
80 | outb((tf->device & HIHI) | drive->select, | ||
81 | io_ports->device_addr); | ||
82 | } | ||
83 | |||
84 | static void h8300_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | ||
85 | { | ||
86 | ide_hwif_t *hwif = drive->hwif; | ||
87 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
88 | struct ide_taskfile *tf = &cmd->tf; | ||
89 | |||
90 | /* be sure we're looking at the low order bits */ | ||
91 | outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
92 | |||
93 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | ||
94 | tf->error = inb(io_ports->feature_addr); | ||
95 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | ||
96 | tf->nsect = inb(io_ports->nsect_addr); | ||
97 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | ||
98 | tf->lbal = inb(io_ports->lbal_addr); | ||
99 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | ||
100 | tf->lbam = inb(io_ports->lbam_addr); | ||
101 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | ||
102 | tf->lbah = inb(io_ports->lbah_addr); | ||
103 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
104 | tf->device = inb(io_ports->device_addr); | ||
105 | |||
106 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
107 | outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
108 | |||
109 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
110 | tf->hob_error = inb(io_ports->feature_addr); | ||
111 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
112 | tf->hob_nsect = inb(io_ports->nsect_addr); | ||
113 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
114 | tf->hob_lbal = inb(io_ports->lbal_addr); | ||
115 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
116 | tf->hob_lbam = inb(io_ports->lbam_addr); | ||
117 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
118 | tf->hob_lbah = inb(io_ports->lbah_addr); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void mm_outsw(unsigned long addr, void *buf, u32 len) | 25 | static void mm_outsw(unsigned long addr, void *buf, u32 len) |
123 | { | 26 | { |
124 | unsigned short *bp = (unsigned short *)buf; | 27 | unsigned short *bp = (unsigned short *)buf; |
@@ -152,8 +55,8 @@ static const struct ide_tp_ops h8300_tp_ops = { | |||
152 | .write_devctl = ide_write_devctl, | 55 | .write_devctl = ide_write_devctl, |
153 | 56 | ||
154 | .dev_select = ide_dev_select, | 57 | .dev_select = ide_dev_select, |
155 | .tf_load = h8300_tf_load, | 58 | .tf_load = ide_tf_load, |
156 | .tf_read = h8300_tf_read, | 59 | .tf_read = ide_tf_read, |
157 | 60 | ||
158 | .input_data = h8300_input_data, | 61 | .input_data = h8300_input_data, |
159 | .output_data = h8300_output_data, | 62 | .output_data = h8300_output_data, |
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c index 9cac281d82c4..46721c454518 100644 --- a/drivers/ide/ide-io-std.c +++ b/drivers/ide/ide-io-std.c | |||
@@ -85,98 +85,57 @@ void ide_dev_select(ide_drive_t *drive) | |||
85 | } | 85 | } |
86 | EXPORT_SYMBOL_GPL(ide_dev_select); | 86 | EXPORT_SYMBOL_GPL(ide_dev_select); |
87 | 87 | ||
88 | void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | 88 | void ide_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) |
89 | { | 89 | { |
90 | ide_hwif_t *hwif = drive->hwif; | 90 | ide_hwif_t *hwif = drive->hwif; |
91 | struct ide_io_ports *io_ports = &hwif->io_ports; | 91 | struct ide_io_ports *io_ports = &hwif->io_ports; |
92 | struct ide_taskfile *tf = &cmd->tf; | ||
93 | void (*tf_outb)(u8 addr, unsigned long port); | 92 | void (*tf_outb)(u8 addr, unsigned long port); |
94 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 93 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
95 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
96 | 94 | ||
97 | if (mmio) | 95 | if (mmio) |
98 | tf_outb = ide_mm_outb; | 96 | tf_outb = ide_mm_outb; |
99 | else | 97 | else |
100 | tf_outb = ide_outb; | 98 | tf_outb = ide_outb; |
101 | 99 | ||
102 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 100 | if (valid & IDE_VALID_FEATURE) |
103 | HIHI = 0xFF; | ||
104 | |||
105 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
106 | tf_outb(tf->hob_feature, io_ports->feature_addr); | ||
107 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
108 | tf_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
109 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
110 | tf_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
111 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
112 | tf_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
113 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
114 | tf_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
115 | |||
116 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
117 | tf_outb(tf->feature, io_ports->feature_addr); | 101 | tf_outb(tf->feature, io_ports->feature_addr); |
118 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | 102 | if (valid & IDE_VALID_NSECT) |
119 | tf_outb(tf->nsect, io_ports->nsect_addr); | 103 | tf_outb(tf->nsect, io_ports->nsect_addr); |
120 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | 104 | if (valid & IDE_VALID_LBAL) |
121 | tf_outb(tf->lbal, io_ports->lbal_addr); | 105 | tf_outb(tf->lbal, io_ports->lbal_addr); |
122 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | 106 | if (valid & IDE_VALID_LBAM) |
123 | tf_outb(tf->lbam, io_ports->lbam_addr); | 107 | tf_outb(tf->lbam, io_ports->lbam_addr); |
124 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | 108 | if (valid & IDE_VALID_LBAH) |
125 | tf_outb(tf->lbah, io_ports->lbah_addr); | 109 | tf_outb(tf->lbah, io_ports->lbah_addr); |
126 | 110 | if (valid & IDE_VALID_DEVICE) | |
127 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | 111 | tf_outb(tf->device, io_ports->device_addr); |
128 | tf_outb((tf->device & HIHI) | drive->select, | ||
129 | io_ports->device_addr); | ||
130 | } | 112 | } |
131 | EXPORT_SYMBOL_GPL(ide_tf_load); | 113 | EXPORT_SYMBOL_GPL(ide_tf_load); |
132 | 114 | ||
133 | void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | 115 | void ide_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) |
134 | { | 116 | { |
135 | ide_hwif_t *hwif = drive->hwif; | 117 | ide_hwif_t *hwif = drive->hwif; |
136 | struct ide_io_ports *io_ports = &hwif->io_ports; | 118 | struct ide_io_ports *io_ports = &hwif->io_ports; |
137 | struct ide_taskfile *tf = &cmd->tf; | ||
138 | void (*tf_outb)(u8 addr, unsigned long port); | ||
139 | u8 (*tf_inb)(unsigned long port); | 119 | u8 (*tf_inb)(unsigned long port); |
140 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 120 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
141 | 121 | ||
142 | if (mmio) { | 122 | if (mmio) |
143 | tf_outb = ide_mm_outb; | ||
144 | tf_inb = ide_mm_inb; | 123 | tf_inb = ide_mm_inb; |
145 | } else { | 124 | else |
146 | tf_outb = ide_outb; | ||
147 | tf_inb = ide_inb; | 125 | tf_inb = ide_inb; |
148 | } | ||
149 | |||
150 | /* be sure we're looking at the low order bits */ | ||
151 | tf_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
152 | 126 | ||
153 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | 127 | if (valid & IDE_VALID_ERROR) |
154 | tf->error = tf_inb(io_ports->feature_addr); | 128 | tf->error = tf_inb(io_ports->feature_addr); |
155 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 129 | if (valid & IDE_VALID_NSECT) |
156 | tf->nsect = tf_inb(io_ports->nsect_addr); | 130 | tf->nsect = tf_inb(io_ports->nsect_addr); |
157 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 131 | if (valid & IDE_VALID_LBAL) |
158 | tf->lbal = tf_inb(io_ports->lbal_addr); | 132 | tf->lbal = tf_inb(io_ports->lbal_addr); |
159 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | 133 | if (valid & IDE_VALID_LBAM) |
160 | tf->lbam = tf_inb(io_ports->lbam_addr); | 134 | tf->lbam = tf_inb(io_ports->lbam_addr); |
161 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | 135 | if (valid & IDE_VALID_LBAH) |
162 | tf->lbah = tf_inb(io_ports->lbah_addr); | 136 | tf->lbah = tf_inb(io_ports->lbah_addr); |
163 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | 137 | if (valid & IDE_VALID_DEVICE) |
164 | tf->device = tf_inb(io_ports->device_addr); | 138 | tf->device = tf_inb(io_ports->device_addr); |
165 | |||
166 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
167 | tf_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
168 | |||
169 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
170 | tf->hob_error = tf_inb(io_ports->feature_addr); | ||
171 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
172 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); | ||
173 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
174 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); | ||
175 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
176 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); | ||
177 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
178 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); | ||
179 | } | ||
180 | } | 139 | } |
181 | EXPORT_SYMBOL_GPL(ide_tf_read); | 140 | EXPORT_SYMBOL_GPL(ide_tf_read); |
182 | 141 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1deb6d29b186..2ae02b8d7f8e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -86,18 +86,18 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
86 | 86 | ||
87 | tp_ops->input_data(drive, cmd, data, 2); | 87 | tp_ops->input_data(drive, cmd, data, 2); |
88 | 88 | ||
89 | tf->data = data[0]; | 89 | cmd->tf.data = data[0]; |
90 | tf->hob_data = data[1]; | 90 | cmd->hob.data = data[1]; |
91 | } | 91 | } |
92 | 92 | ||
93 | tp_ops->tf_read(drive, cmd); | 93 | ide_tf_readback(drive, cmd); |
94 | 94 | ||
95 | if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) && | 95 | if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) && |
96 | tf_cmd == ATA_CMD_IDLEIMMEDIATE) { | 96 | tf_cmd == ATA_CMD_IDLEIMMEDIATE) { |
97 | if (tf->lbal != 0xc4) { | 97 | if (tf->lbal != 0xc4) { |
98 | printk(KERN_ERR "%s: head unload failed!\n", | 98 | printk(KERN_ERR "%s: head unload failed!\n", |
99 | drive->name); | 99 | drive->name); |
100 | ide_tf_dump(drive->name, tf); | 100 | ide_tf_dump(drive->name, cmd); |
101 | } else | 101 | } else |
102 | drive->dev_flags |= IDE_DFLAG_PARKED; | 102 | drive->dev_flags |= IDE_DFLAG_PARKED; |
103 | } | 103 | } |
@@ -205,8 +205,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) | |||
205 | return ide_stopped; | 205 | return ide_stopped; |
206 | } | 206 | } |
207 | 207 | ||
208 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE | | 208 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
209 | IDE_TFLAG_CUSTOM_HANDLER; | 209 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
210 | cmd.tf_flags = IDE_TFLAG_CUSTOM_HANDLER; | ||
210 | 211 | ||
211 | do_rw_taskfile(drive, &cmd); | 212 | do_rw_taskfile(drive, &cmd); |
212 | 213 | ||
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 770142767437..c1c25ebbaa1f 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
@@ -141,11 +141,12 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) | |||
141 | tf->lbal = args[1]; | 141 | tf->lbal = args[1]; |
142 | tf->lbam = 0x4f; | 142 | tf->lbam = 0x4f; |
143 | tf->lbah = 0xc2; | 143 | tf->lbah = 0xc2; |
144 | cmd.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; | 144 | cmd.valid.out.tf = IDE_VALID_OUT_TF; |
145 | cmd.valid.in.tf = IDE_VALID_NSECT; | ||
145 | } else { | 146 | } else { |
146 | tf->nsect = args[1]; | 147 | tf->nsect = args[1]; |
147 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | | 148 | cmd.valid.out.tf = IDE_VALID_FEATURE | IDE_VALID_NSECT; |
148 | IDE_TFLAG_IN_NSECT; | 149 | cmd.valid.in.tf = IDE_VALID_NSECT; |
149 | } | 150 | } |
150 | tf->command = args[0]; | 151 | tf->command = args[0]; |
151 | cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA; | 152 | cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA; |
@@ -205,14 +206,15 @@ static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) | |||
205 | return -EFAULT; | 206 | return -EFAULT; |
206 | 207 | ||
207 | memset(&cmd, 0, sizeof(cmd)); | 208 | memset(&cmd, 0, sizeof(cmd)); |
208 | memcpy(&cmd.tf_array[7], &args[1], 6); | 209 | memcpy(&cmd.tf.feature, &args[1], 6); |
209 | cmd.tf.command = args[0]; | 210 | cmd.tf.command = args[0]; |
210 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 211 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
212 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
211 | 213 | ||
212 | err = ide_no_data_taskfile(drive, &cmd); | 214 | err = ide_no_data_taskfile(drive, &cmd); |
213 | 215 | ||
214 | args[0] = cmd.tf.command; | 216 | args[0] = cmd.tf.command; |
215 | memcpy(&args[1], &cmd.tf_array[7], 6); | 217 | memcpy(&args[1], &cmd.tf.feature, 6); |
216 | 218 | ||
217 | if (copy_to_user(p, args, 7)) | 219 | if (copy_to_user(p, args, 7)) |
218 | err = -EFAULT; | 220 | err = -EFAULT; |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 27bb70ddd459..c19a221b1e18 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -37,14 +37,11 @@ void SELECT_MASK(ide_drive_t *drive, int mask) | |||
37 | 37 | ||
38 | u8 ide_read_error(ide_drive_t *drive) | 38 | u8 ide_read_error(ide_drive_t *drive) |
39 | { | 39 | { |
40 | struct ide_cmd cmd; | 40 | struct ide_taskfile tf; |
41 | 41 | ||
42 | memset(&cmd, 0, sizeof(cmd)); | 42 | drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_ERROR); |
43 | cmd.tf_flags = IDE_TFLAG_IN_ERROR; | ||
44 | 43 | ||
45 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 44 | return tf.error; |
46 | |||
47 | return cmd.tf.error; | ||
48 | } | 45 | } |
49 | EXPORT_SYMBOL_GPL(ide_read_error); | 46 | EXPORT_SYMBOL_GPL(ide_read_error); |
50 | 47 | ||
@@ -312,10 +309,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
312 | { | 309 | { |
313 | ide_hwif_t *hwif = drive->hwif; | 310 | ide_hwif_t *hwif = drive->hwif; |
314 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 311 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
312 | struct ide_taskfile tf; | ||
315 | u16 *id = drive->id, i; | 313 | u16 *id = drive->id, i; |
316 | int error = 0; | 314 | int error = 0; |
317 | u8 stat; | 315 | u8 stat; |
318 | struct ide_cmd cmd; | ||
319 | 316 | ||
320 | #ifdef CONFIG_BLK_DEV_IDEDMA | 317 | #ifdef CONFIG_BLK_DEV_IDEDMA |
321 | if (hwif->dma_ops) /* check if host supports DMA */ | 318 | if (hwif->dma_ops) /* check if host supports DMA */ |
@@ -347,12 +344,11 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
347 | udelay(1); | 344 | udelay(1); |
348 | tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS); | 345 | tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS); |
349 | 346 | ||
350 | memset(&cmd, 0, sizeof(cmd)); | 347 | memset(&tf, 0, sizeof(tf)); |
351 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT; | 348 | tf.feature = SETFEATURES_XFER; |
352 | cmd.tf.feature = SETFEATURES_XFER; | 349 | tf.nsect = speed; |
353 | cmd.tf.nsect = speed; | ||
354 | 350 | ||
355 | tp_ops->tf_load(drive, &cmd); | 351 | tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE | IDE_VALID_NSECT); |
356 | 352 | ||
357 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); | 353 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); |
358 | 354 | ||
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 217b7fdf2b17..56ff8c46c7d1 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
@@ -49,16 +49,17 @@ static void ide_dump_opcode(ide_drive_t *drive) | |||
49 | printk(KERN_CONT "0x%02x\n", cmd->tf.command); | 49 | printk(KERN_CONT "0x%02x\n", cmd->tf.command); |
50 | } | 50 | } |
51 | 51 | ||
52 | u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48) | 52 | u64 ide_get_lba_addr(struct ide_cmd *cmd, int lba48) |
53 | { | 53 | { |
54 | struct ide_taskfile *tf = &cmd->tf; | ||
54 | u32 high, low; | 55 | u32 high, low; |
55 | 56 | ||
56 | if (lba48) | ||
57 | high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) | | ||
58 | tf->hob_lbal; | ||
59 | else | ||
60 | high = tf->device & 0xf; | ||
61 | low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; | 57 | low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; |
58 | if (lba48) { | ||
59 | tf = &cmd->hob; | ||
60 | high = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; | ||
61 | } else | ||
62 | high = tf->device & 0xf; | ||
62 | 63 | ||
63 | return ((u64)high << 24) | low; | 64 | return ((u64)high << 24) | low; |
64 | } | 65 | } |
@@ -71,17 +72,18 @@ static void ide_dump_sector(ide_drive_t *drive) | |||
71 | u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); | 72 | u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); |
72 | 73 | ||
73 | memset(&cmd, 0, sizeof(cmd)); | 74 | memset(&cmd, 0, sizeof(cmd)); |
74 | if (lba48) | 75 | if (lba48) { |
75 | cmd.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA | | 76 | cmd.valid.in.tf = IDE_VALID_LBA; |
76 | IDE_TFLAG_LBA48; | 77 | cmd.valid.in.hob = IDE_VALID_LBA; |
77 | else | 78 | cmd.tf_flags = IDE_TFLAG_LBA48; |
78 | cmd.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; | 79 | } else |
80 | cmd.valid.in.tf = IDE_VALID_LBA | IDE_VALID_DEVICE; | ||
79 | 81 | ||
80 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 82 | ide_tf_readback(drive, &cmd); |
81 | 83 | ||
82 | if (lba48 || (tf->device & ATA_LBA)) | 84 | if (lba48 || (tf->device & ATA_LBA)) |
83 | printk(KERN_CONT ", LBAsect=%llu", | 85 | printk(KERN_CONT ", LBAsect=%llu", |
84 | (unsigned long long)ide_get_lba_addr(tf, lba48)); | 86 | (unsigned long long)ide_get_lba_addr(&cmd, lba48)); |
85 | else | 87 | else |
86 | printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, | 88 | printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, |
87 | tf->device & 0xf, tf->lbal); | 89 | tf->device & 0xf, tf->lbal); |
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 9490b446519f..310d03f2b5b7 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c | |||
@@ -74,7 +74,8 @@ ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) | |||
74 | tf->lbal = 0x4c; | 74 | tf->lbal = 0x4c; |
75 | tf->lbam = 0x4e; | 75 | tf->lbam = 0x4e; |
76 | tf->lbah = 0x55; | 76 | tf->lbah = 0x55; |
77 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 77 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
78 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
78 | } else /* cmd == REQ_UNPARK_HEADS */ | 79 | } else /* cmd == REQ_UNPARK_HEADS */ |
79 | tf->command = ATA_CMD_CHK_POWER; | 80 | tf->command = ATA_CMD_CHK_POWER; |
80 | 81 | ||
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index bb7858ebb7d1..0d8a151c0a01 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c | |||
@@ -163,7 +163,8 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | |||
163 | return ide_stopped; | 163 | return ide_stopped; |
164 | 164 | ||
165 | out_do_tf: | 165 | out_do_tf: |
166 | cmd->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 166 | cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
167 | cmd->valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
167 | cmd->protocol = ATA_PROT_NODATA; | 168 | cmd->protocol = ATA_PROT_NODATA; |
168 | 169 | ||
169 | return do_rw_taskfile(drive, cmd); | 170 | return do_rw_taskfile(drive, cmd); |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index d8c1c3e735bb..7f264ed1141b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -283,13 +283,11 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id) | |||
283 | * identify command to be sure of reply | 283 | * identify command to be sure of reply |
284 | */ | 284 | */ |
285 | if (cmd == ATA_CMD_ID_ATAPI) { | 285 | if (cmd == ATA_CMD_ID_ATAPI) { |
286 | struct ide_cmd cmd; | 286 | struct ide_taskfile tf; |
287 | 287 | ||
288 | memset(&cmd, 0, sizeof(cmd)); | 288 | memset(&tf, 0, sizeof(tf)); |
289 | /* disable DMA & overlap */ | 289 | /* disable DMA & overlap */ |
290 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE; | 290 | tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE); |
291 | |||
292 | tp_ops->tf_load(drive, &cmd); | ||
293 | } | 291 | } |
294 | 292 | ||
295 | /* ask drive for ID */ | 293 | /* ask drive for ID */ |
@@ -337,14 +335,11 @@ int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) | |||
337 | 335 | ||
338 | static u8 ide_read_device(ide_drive_t *drive) | 336 | static u8 ide_read_device(ide_drive_t *drive) |
339 | { | 337 | { |
340 | struct ide_cmd cmd; | 338 | struct ide_taskfile tf; |
341 | |||
342 | memset(&cmd, 0, sizeof(cmd)); | ||
343 | cmd.tf_flags = IDE_TFLAG_IN_DEVICE; | ||
344 | 339 | ||
345 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 340 | drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_DEVICE); |
346 | 341 | ||
347 | return cmd.tf.device; | 342 | return tf.device; |
348 | } | 343 | } |
349 | 344 | ||
350 | /** | 345 | /** |
@@ -1314,6 +1309,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | |||
1314 | host->get_lock = d->get_lock; | 1309 | host->get_lock = d->get_lock; |
1315 | host->release_lock = d->release_lock; | 1310 | host->release_lock = d->release_lock; |
1316 | host->host_flags = d->host_flags; | 1311 | host->host_flags = d->host_flags; |
1312 | host->irq_flags = d->irq_flags; | ||
1317 | } | 1313 | } |
1318 | 1314 | ||
1319 | return host; | 1315 | return host; |
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 10a88bf3eefa..3242698832a4 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
@@ -204,8 +204,8 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) | |||
204 | cmd.tf.command = ATA_CMD_SET_FEATURES; | 204 | cmd.tf.command = ATA_CMD_SET_FEATURES; |
205 | cmd.tf.feature = SETFEATURES_XFER; | 205 | cmd.tf.feature = SETFEATURES_XFER; |
206 | cmd.tf.nsect = (u8)arg; | 206 | cmd.tf.nsect = (u8)arg; |
207 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | | 207 | cmd.valid.out.tf = IDE_VALID_FEATURE | IDE_VALID_NSECT; |
208 | IDE_TFLAG_IN_NSECT; | 208 | cmd.valid.in.tf = IDE_VALID_NSECT; |
209 | 209 | ||
210 | err = ide_no_data_taskfile(drive, &cmd); | 210 | err = ide_no_data_taskfile(drive, &cmd); |
211 | 211 | ||
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 243421ce40d0..4aa6223c11be 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -23,17 +23,33 @@ | |||
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | 25 | ||
26 | void ide_tf_dump(const char *s, struct ide_taskfile *tf) | 26 | void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd) |
27 | { | ||
28 | ide_hwif_t *hwif = drive->hwif; | ||
29 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
30 | |||
31 | /* Be sure we're looking at the low order bytes */ | ||
32 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
33 | |||
34 | tp_ops->tf_read(drive, &cmd->tf, cmd->valid.in.tf); | ||
35 | |||
36 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
37 | tp_ops->write_devctl(hwif, ATA_HOB | ATA_DEVCTL_OBS); | ||
38 | |||
39 | tp_ops->tf_read(drive, &cmd->hob, cmd->valid.in.hob); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | void ide_tf_dump(const char *s, struct ide_cmd *cmd) | ||
27 | { | 44 | { |
28 | #ifdef DEBUG | 45 | #ifdef DEBUG |
29 | printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " | 46 | printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " |
30 | "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", | 47 | "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", |
31 | s, tf->feature, tf->nsect, tf->lbal, | 48 | s, cmd->tf.feature, cmd->tf.nsect, |
32 | tf->lbam, tf->lbah, tf->device, tf->command); | 49 | cmd->tf.lbal, cmd->tf.lbam, cmd->tf.lbah, |
33 | printk("%s: hob: nsect 0x%02x lbal 0x%02x " | 50 | cmd->tf.device, cmd->tf.command); |
34 | "lbam 0x%02x lbah 0x%02x\n", | 51 | printk("%s: hob: nsect 0x%02x lbal 0x%02x lbam 0x%02x lbah 0x%02x\n", |
35 | s, tf->hob_nsect, tf->hob_lbal, | 52 | s, cmd->hob.nsect, cmd->hob.lbal, cmd->hob.lbam, cmd->hob.lbah); |
36 | tf->hob_lbam, tf->hob_lbah); | ||
37 | #endif | 53 | #endif |
38 | } | 54 | } |
39 | 55 | ||
@@ -47,7 +63,8 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) | |||
47 | cmd.tf.command = ATA_CMD_ID_ATA; | 63 | cmd.tf.command = ATA_CMD_ID_ATA; |
48 | else | 64 | else |
49 | cmd.tf.command = ATA_CMD_ID_ATAPI; | 65 | cmd.tf.command = ATA_CMD_ID_ATAPI; |
50 | cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | 66 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
67 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | ||
51 | cmd.protocol = ATA_PROT_PIO; | 68 | cmd.protocol = ATA_PROT_PIO; |
52 | 69 | ||
53 | return ide_raw_taskfile(drive, &cmd, buf, 1); | 70 | return ide_raw_taskfile(drive, &cmd, buf, 1); |
@@ -79,16 +96,27 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) | |||
79 | memcpy(cmd, orig_cmd, sizeof(*cmd)); | 96 | memcpy(cmd, orig_cmd, sizeof(*cmd)); |
80 | 97 | ||
81 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { | 98 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { |
82 | ide_tf_dump(drive->name, tf); | 99 | ide_tf_dump(drive->name, cmd); |
83 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | 100 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
84 | SELECT_MASK(drive, 0); | 101 | SELECT_MASK(drive, 0); |
85 | 102 | ||
86 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | 103 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { |
87 | u8 data[2] = { tf->data, tf->hob_data }; | 104 | u8 data[2] = { cmd->tf.data, cmd->hob.data }; |
88 | 105 | ||
89 | tp_ops->output_data(drive, cmd, data, 2); | 106 | tp_ops->output_data(drive, cmd, data, 2); |
90 | } | 107 | } |
91 | tp_ops->tf_load(drive, cmd); | 108 | |
109 | if (cmd->valid.out.tf & IDE_VALID_DEVICE) { | ||
110 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? | ||
111 | 0xE0 : 0xEF; | ||
112 | |||
113 | if (!(cmd->ftf_flags & IDE_FTFLAG_FLAGGED)) | ||
114 | cmd->tf.device &= HIHI; | ||
115 | cmd->tf.device |= drive->select; | ||
116 | } | ||
117 | |||
118 | tp_ops->tf_load(drive, &cmd->hob, cmd->valid.out.hob); | ||
119 | tp_ops->tf_load(drive, &cmd->tf, cmd->valid.out.tf); | ||
92 | } | 120 | } |
93 | 121 | ||
94 | switch (cmd->protocol) { | 122 | switch (cmd->protocol) { |
@@ -489,16 +517,17 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
489 | 517 | ||
490 | memset(&cmd, 0, sizeof(cmd)); | 518 | memset(&cmd, 0, sizeof(cmd)); |
491 | 519 | ||
492 | memcpy(&cmd.tf_array[0], req_task->hob_ports, | 520 | memcpy(&cmd.hob, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); |
493 | HDIO_DRIVE_HOB_HDR_SIZE - 2); | 521 | memcpy(&cmd.tf, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); |
494 | memcpy(&cmd.tf_array[6], req_task->io_ports, | ||
495 | HDIO_DRIVE_TASK_HDR_SIZE); | ||
496 | 522 | ||
497 | cmd.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE | | 523 | cmd.valid.out.tf = IDE_VALID_DEVICE; |
498 | IDE_TFLAG_IN_TF; | 524 | cmd.valid.in.tf = IDE_VALID_DEVICE | IDE_VALID_IN_TF; |
525 | cmd.tf_flags = IDE_TFLAG_IO_16BIT; | ||
499 | 526 | ||
500 | if (drive->dev_flags & IDE_DFLAG_LBA48) | 527 | if (drive->dev_flags & IDE_DFLAG_LBA48) { |
501 | cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB); | 528 | cmd.tf_flags |= IDE_TFLAG_LBA48; |
529 | cmd.valid.in.hob = IDE_VALID_IN_HOB; | ||
530 | } | ||
502 | 531 | ||
503 | if (req_task->out_flags.all) { | 532 | if (req_task->out_flags.all) { |
504 | cmd.ftf_flags |= IDE_FTFLAG_FLAGGED; | 533 | cmd.ftf_flags |= IDE_FTFLAG_FLAGGED; |
@@ -507,28 +536,28 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
507 | cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA; | 536 | cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA; |
508 | 537 | ||
509 | if (req_task->out_flags.b.nsector_hob) | 538 | if (req_task->out_flags.b.nsector_hob) |
510 | cmd.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; | 539 | cmd.valid.out.hob |= IDE_VALID_NSECT; |
511 | if (req_task->out_flags.b.sector_hob) | 540 | if (req_task->out_flags.b.sector_hob) |
512 | cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; | 541 | cmd.valid.out.hob |= IDE_VALID_LBAL; |
513 | if (req_task->out_flags.b.lcyl_hob) | 542 | if (req_task->out_flags.b.lcyl_hob) |
514 | cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; | 543 | cmd.valid.out.hob |= IDE_VALID_LBAM; |
515 | if (req_task->out_flags.b.hcyl_hob) | 544 | if (req_task->out_flags.b.hcyl_hob) |
516 | cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; | 545 | cmd.valid.out.hob |= IDE_VALID_LBAH; |
517 | 546 | ||
518 | if (req_task->out_flags.b.error_feature) | 547 | if (req_task->out_flags.b.error_feature) |
519 | cmd.tf_flags |= IDE_TFLAG_OUT_FEATURE; | 548 | cmd.valid.out.tf |= IDE_VALID_FEATURE; |
520 | if (req_task->out_flags.b.nsector) | 549 | if (req_task->out_flags.b.nsector) |
521 | cmd.tf_flags |= IDE_TFLAG_OUT_NSECT; | 550 | cmd.valid.out.tf |= IDE_VALID_NSECT; |
522 | if (req_task->out_flags.b.sector) | 551 | if (req_task->out_flags.b.sector) |
523 | cmd.tf_flags |= IDE_TFLAG_OUT_LBAL; | 552 | cmd.valid.out.tf |= IDE_VALID_LBAL; |
524 | if (req_task->out_flags.b.lcyl) | 553 | if (req_task->out_flags.b.lcyl) |
525 | cmd.tf_flags |= IDE_TFLAG_OUT_LBAM; | 554 | cmd.valid.out.tf |= IDE_VALID_LBAM; |
526 | if (req_task->out_flags.b.hcyl) | 555 | if (req_task->out_flags.b.hcyl) |
527 | cmd.tf_flags |= IDE_TFLAG_OUT_LBAH; | 556 | cmd.valid.out.tf |= IDE_VALID_LBAH; |
528 | } else { | 557 | } else { |
529 | cmd.tf_flags |= IDE_TFLAG_OUT_TF; | 558 | cmd.valid.out.tf |= IDE_VALID_OUT_TF; |
530 | if (cmd.tf_flags & IDE_TFLAG_LBA48) | 559 | if (cmd.tf_flags & IDE_TFLAG_LBA48) |
531 | cmd.tf_flags |= IDE_TFLAG_OUT_HOB; | 560 | cmd.valid.out.hob |= IDE_VALID_OUT_HOB; |
532 | } | 561 | } |
533 | 562 | ||
534 | if (req_task->in_flags.b.data) | 563 | if (req_task->in_flags.b.data) |
@@ -594,7 +623,7 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
594 | if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) | 623 | if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) |
595 | nsect = 0; | 624 | nsect = 0; |
596 | else if (!nsect) { | 625 | else if (!nsect) { |
597 | nsect = (cmd.tf.hob_nsect << 8) | cmd.tf.nsect; | 626 | nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect; |
598 | 627 | ||
599 | if (!nsect) { | 628 | if (!nsect) { |
600 | printk(KERN_ERR "%s: in/out command without data\n", | 629 | printk(KERN_ERR "%s: in/out command without data\n", |
@@ -606,10 +635,8 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
606 | 635 | ||
607 | err = ide_raw_taskfile(drive, &cmd, data_buf, nsect); | 636 | err = ide_raw_taskfile(drive, &cmd, data_buf, nsect); |
608 | 637 | ||
609 | memcpy(req_task->hob_ports, &cmd.tf_array[0], | 638 | memcpy(req_task->hob_ports, &cmd.hob, HDIO_DRIVE_HOB_HDR_SIZE - 2); |
610 | HDIO_DRIVE_HOB_HDR_SIZE - 2); | 639 | memcpy(req_task->io_ports, &cmd.tf, HDIO_DRIVE_TASK_HDR_SIZE); |
611 | memcpy(req_task->io_ports, &cmd.tf_array[6], | ||
612 | HDIO_DRIVE_TASK_HDR_SIZE); | ||
613 | 640 | ||
614 | if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) && | 641 | if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) && |
615 | req_task->in_flags.all == 0) { | 642 | req_task->in_flags.all == 0) { |
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 71a39fb3856f..95327a2c2422 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c | |||
@@ -61,41 +61,23 @@ static u8 superio_dma_sff_read_status(ide_hwif_t *hwif) | |||
61 | return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS); | 61 | return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS); |
62 | } | 62 | } |
63 | 63 | ||
64 | static void superio_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | 64 | static void superio_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, |
65 | u8 valid) | ||
65 | { | 66 | { |
66 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | 67 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; |
67 | struct ide_taskfile *tf = &cmd->tf; | ||
68 | 68 | ||
69 | /* be sure we're looking at the low order bits */ | 69 | if (valid & IDE_VALID_ERROR) |
70 | outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
71 | |||
72 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | ||
73 | tf->error = inb(io_ports->feature_addr); | 70 | tf->error = inb(io_ports->feature_addr); |
74 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 71 | if (valid & IDE_VALID_NSECT) |
75 | tf->nsect = inb(io_ports->nsect_addr); | 72 | tf->nsect = inb(io_ports->nsect_addr); |
76 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 73 | if (valid & IDE_VALID_LBAL) |
77 | tf->lbal = inb(io_ports->lbal_addr); | 74 | tf->lbal = inb(io_ports->lbal_addr); |
78 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | 75 | if (valid & IDE_VALID_LBAM) |
79 | tf->lbam = inb(io_ports->lbam_addr); | 76 | tf->lbam = inb(io_ports->lbam_addr); |
80 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | 77 | if (valid & IDE_VALID_LBAH) |
81 | tf->lbah = inb(io_ports->lbah_addr); | 78 | tf->lbah = inb(io_ports->lbah_addr); |
82 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | 79 | if (valid & IDE_VALID_DEVICE) |
83 | tf->device = superio_ide_inb(io_ports->device_addr); | 80 | tf->device = superio_ide_inb(io_ports->device_addr); |
84 | |||
85 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
86 | outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
87 | |||
88 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
89 | tf->hob_error = inb(io_ports->feature_addr); | ||
90 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
91 | tf->hob_nsect = inb(io_ports->nsect_addr); | ||
92 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
93 | tf->hob_lbal = inb(io_ports->lbal_addr); | ||
94 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
95 | tf->hob_lbam = inb(io_ports->lbam_addr); | ||
96 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
97 | tf->hob_lbah = inb(io_ports->lbah_addr); | ||
98 | } | ||
99 | } | 81 | } |
100 | 82 | ||
101 | static void ns87415_dev_select(ide_drive_t *drive); | 83 | static void ns87415_dev_select(ide_drive_t *drive); |
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c index d007e7f66598..c79346679244 100644 --- a/drivers/ide/q40ide.c +++ b/drivers/ide/q40ide.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
17 | #include <linux/ide.h> | 17 | #include <linux/ide.h> |
18 | 18 | ||
19 | #include <asm/ide.h> | ||
20 | |||
19 | /* | 21 | /* |
20 | * Bases of the IDE interfaces | 22 | * Bases of the IDE interfaces |
21 | */ | 23 | */ |
@@ -77,8 +79,10 @@ static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, | |||
77 | { | 79 | { |
78 | unsigned long data_addr = drive->hwif->io_ports.data_addr; | 80 | unsigned long data_addr = drive->hwif->io_ports.data_addr; |
79 | 81 | ||
80 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) | 82 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) { |
81 | return insw(data_addr, buf, (len + 1) / 2); | 83 | __ide_mm_insw(data_addr, buf, (len + 1) / 2); |
84 | return; | ||
85 | } | ||
82 | 86 | ||
83 | raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2); | 87 | raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2); |
84 | } | 88 | } |
@@ -88,8 +92,10 @@ static void q40ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, | |||
88 | { | 92 | { |
89 | unsigned long data_addr = drive->hwif->io_ports.data_addr; | 93 | unsigned long data_addr = drive->hwif->io_ports.data_addr; |
90 | 94 | ||
91 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) | 95 | if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) { |
92 | return outsw(data_addr, buf, (len + 1) / 2); | 96 | __ide_mm_outsw(data_addr, buf, (len + 1) / 2); |
97 | return; | ||
98 | } | ||
93 | 99 | ||
94 | raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2); | 100 | raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2); |
95 | } | 101 | } |
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index 6d8dbd9c10bc..5be41f25204f 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c | |||
@@ -337,7 +337,6 @@ static void scc_dma_start(ide_drive_t *drive) | |||
337 | 337 | ||
338 | /* start DMA */ | 338 | /* start DMA */ |
339 | scc_ide_outb(dma_cmd | 1, hwif->dma_base); | 339 | scc_ide_outb(dma_cmd | 1, hwif->dma_base); |
340 | wmb(); | ||
341 | } | 340 | } |
342 | 341 | ||
343 | static int __scc_dma_end(ide_drive_t *drive) | 342 | static int __scc_dma_end(ide_drive_t *drive) |
@@ -354,7 +353,6 @@ static int __scc_dma_end(ide_drive_t *drive) | |||
354 | /* clear the INTR & ERROR bits */ | 353 | /* clear the INTR & ERROR bits */ |
355 | scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); | 354 | scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); |
356 | /* verify good DMA status */ | 355 | /* verify good DMA status */ |
357 | wmb(); | ||
358 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; | 356 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; |
359 | } | 357 | } |
360 | 358 | ||
@@ -647,77 +645,40 @@ static int __devinit init_setup_scc(struct pci_dev *dev, | |||
647 | return rc; | 645 | return rc; |
648 | } | 646 | } |
649 | 647 | ||
650 | static void scc_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | 648 | static void scc_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) |
651 | { | 649 | { |
652 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | 650 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; |
653 | struct ide_taskfile *tf = &cmd->tf; | 651 | |
654 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | 652 | if (valid & IDE_VALID_FEATURE) |
655 | |||
656 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | ||
657 | HIHI = 0xFF; | ||
658 | |||
659 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
660 | scc_ide_outb(tf->hob_feature, io_ports->feature_addr); | ||
661 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
662 | scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
663 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
664 | scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
665 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
666 | scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
667 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
668 | scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
669 | |||
670 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
671 | scc_ide_outb(tf->feature, io_ports->feature_addr); | 653 | scc_ide_outb(tf->feature, io_ports->feature_addr); |
672 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | 654 | if (valid & IDE_VALID_NSECT) |
673 | scc_ide_outb(tf->nsect, io_ports->nsect_addr); | 655 | scc_ide_outb(tf->nsect, io_ports->nsect_addr); |
674 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | 656 | if (valid & IDE_VALID_LBAL) |
675 | scc_ide_outb(tf->lbal, io_ports->lbal_addr); | 657 | scc_ide_outb(tf->lbal, io_ports->lbal_addr); |
676 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | 658 | if (valid & IDE_VALID_LBAM) |
677 | scc_ide_outb(tf->lbam, io_ports->lbam_addr); | 659 | scc_ide_outb(tf->lbam, io_ports->lbam_addr); |
678 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | 660 | if (valid & IDE_VALID_LBAH) |
679 | scc_ide_outb(tf->lbah, io_ports->lbah_addr); | 661 | scc_ide_outb(tf->lbah, io_ports->lbah_addr); |
680 | 662 | if (valid & IDE_VALID_DEVICE) | |
681 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | 663 | scc_ide_outb(tf->device, io_ports->device_addr); |
682 | scc_ide_outb((tf->device & HIHI) | drive->select, | ||
683 | io_ports->device_addr); | ||
684 | } | 664 | } |
685 | 665 | ||
686 | static void scc_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | 666 | static void scc_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) |
687 | { | 667 | { |
688 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | 668 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; |
689 | struct ide_taskfile *tf = &cmd->tf; | ||
690 | |||
691 | /* be sure we're looking at the low order bits */ | ||
692 | scc_ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
693 | 669 | ||
694 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | 670 | if (valid & IDE_VALID_ERROR) |
695 | tf->error = scc_ide_inb(io_ports->feature_addr); | 671 | tf->error = scc_ide_inb(io_ports->feature_addr); |
696 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 672 | if (valid & IDE_VALID_NSECT) |
697 | tf->nsect = scc_ide_inb(io_ports->nsect_addr); | 673 | tf->nsect = scc_ide_inb(io_ports->nsect_addr); |
698 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 674 | if (valid & IDE_VALID_LBAL) |
699 | tf->lbal = scc_ide_inb(io_ports->lbal_addr); | 675 | tf->lbal = scc_ide_inb(io_ports->lbal_addr); |
700 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | 676 | if (valid & IDE_VALID_LBAM) |
701 | tf->lbam = scc_ide_inb(io_ports->lbam_addr); | 677 | tf->lbam = scc_ide_inb(io_ports->lbam_addr); |
702 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | 678 | if (valid & IDE_VALID_LBAH) |
703 | tf->lbah = scc_ide_inb(io_ports->lbah_addr); | 679 | tf->lbah = scc_ide_inb(io_ports->lbah_addr); |
704 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | 680 | if (valid & IDE_VALID_DEVICE) |
705 | tf->device = scc_ide_inb(io_ports->device_addr); | 681 | tf->device = scc_ide_inb(io_ports->device_addr); |
706 | |||
707 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
708 | scc_ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
709 | |||
710 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
711 | tf->hob_error = scc_ide_inb(io_ports->feature_addr); | ||
712 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
713 | tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); | ||
714 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
715 | tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); | ||
716 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
717 | tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); | ||
718 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
719 | tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); | ||
720 | } | ||
721 | } | 682 | } |
722 | 683 | ||
723 | static void scc_input_data(ide_drive_t *drive, struct ide_cmd *cmd, | 684 | static void scc_input_data(ide_drive_t *drive, struct ide_cmd *cmd, |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 4cb79c4c2604..e33d764e2945 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -72,91 +72,6 @@ static void tx4938ide_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
72 | #ifdef __BIG_ENDIAN | 72 | #ifdef __BIG_ENDIAN |
73 | 73 | ||
74 | /* custom iops (independent from SWAP_IO_SPACE) */ | 74 | /* custom iops (independent from SWAP_IO_SPACE) */ |
75 | static u8 tx4938ide_inb(unsigned long port) | ||
76 | { | ||
77 | return __raw_readb((void __iomem *)port); | ||
78 | } | ||
79 | |||
80 | static void tx4938ide_outb(u8 value, unsigned long port) | ||
81 | { | ||
82 | __raw_writeb(value, (void __iomem *)port); | ||
83 | } | ||
84 | |||
85 | static void tx4938ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | ||
86 | { | ||
87 | ide_hwif_t *hwif = drive->hwif; | ||
88 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
89 | struct ide_taskfile *tf = &cmd->tf; | ||
90 | u8 HIHI = cmd->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF; | ||
91 | |||
92 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | ||
93 | HIHI = 0xFF; | ||
94 | |||
95 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
96 | tx4938ide_outb(tf->hob_feature, io_ports->feature_addr); | ||
97 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
98 | tx4938ide_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
99 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
100 | tx4938ide_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
101 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
102 | tx4938ide_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
103 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
104 | tx4938ide_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
105 | |||
106 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
107 | tx4938ide_outb(tf->feature, io_ports->feature_addr); | ||
108 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
109 | tx4938ide_outb(tf->nsect, io_ports->nsect_addr); | ||
110 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
111 | tx4938ide_outb(tf->lbal, io_ports->lbal_addr); | ||
112 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
113 | tx4938ide_outb(tf->lbam, io_ports->lbam_addr); | ||
114 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
115 | tx4938ide_outb(tf->lbah, io_ports->lbah_addr); | ||
116 | |||
117 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
118 | tx4938ide_outb((tf->device & HIHI) | drive->select, | ||
119 | io_ports->device_addr); | ||
120 | } | ||
121 | |||
122 | static void tx4938ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | ||
123 | { | ||
124 | ide_hwif_t *hwif = drive->hwif; | ||
125 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
126 | struct ide_taskfile *tf = &cmd->tf; | ||
127 | |||
128 | /* be sure we're looking at the low order bits */ | ||
129 | tx4938ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
130 | |||
131 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | ||
132 | tf->error = tx4938ide_inb(io_ports->feature_addr); | ||
133 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | ||
134 | tf->nsect = tx4938ide_inb(io_ports->nsect_addr); | ||
135 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | ||
136 | tf->lbal = tx4938ide_inb(io_ports->lbal_addr); | ||
137 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | ||
138 | tf->lbam = tx4938ide_inb(io_ports->lbam_addr); | ||
139 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | ||
140 | tf->lbah = tx4938ide_inb(io_ports->lbah_addr); | ||
141 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
142 | tf->device = tx4938ide_inb(io_ports->device_addr); | ||
143 | |||
144 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
145 | tx4938ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
146 | |||
147 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
148 | tf->hob_error = tx4938ide_inb(io_ports->feature_addr); | ||
149 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
150 | tf->hob_nsect = tx4938ide_inb(io_ports->nsect_addr); | ||
151 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
152 | tf->hob_lbal = tx4938ide_inb(io_ports->lbal_addr); | ||
153 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
154 | tf->hob_lbam = tx4938ide_inb(io_ports->lbam_addr); | ||
155 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
156 | tf->hob_lbah = tx4938ide_inb(io_ports->lbah_addr); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static void tx4938ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, | 75 | static void tx4938ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, |
161 | void *buf, unsigned int len) | 76 | void *buf, unsigned int len) |
162 | { | 77 | { |
@@ -190,8 +105,8 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { | |||
190 | .write_devctl = ide_write_devctl, | 105 | .write_devctl = ide_write_devctl, |
191 | 106 | ||
192 | .dev_select = ide_dev_select, | 107 | .dev_select = ide_dev_select, |
193 | .tf_load = tx4938ide_tf_load, | 108 | .tf_load = ide_tf_load, |
194 | .tf_read = tx4938ide_tf_read, | 109 | .tf_read = ide_tf_read, |
195 | 110 | ||
196 | .input_data = tx4938ide_input_data_swap, | 111 | .input_data = tx4938ide_input_data_swap, |
197 | .output_data = tx4938ide_output_data_swap, | 112 | .output_data = tx4938ide_output_data_swap, |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 0040a9a3e26e..564422d23976 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -327,15 +327,15 @@ static int tx4939ide_dma_end(ide_drive_t *drive) | |||
327 | /* read and clear the INTR & ERROR bits */ | 327 | /* read and clear the INTR & ERROR bits */ |
328 | dma_stat = tx4939ide_clear_dma_status(base); | 328 | dma_stat = tx4939ide_clear_dma_status(base); |
329 | 329 | ||
330 | wmb(); | 330 | #define CHECK_DMA_MASK (ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR) |
331 | 331 | ||
332 | /* verify good DMA status */ | 332 | /* verify good DMA status */ |
333 | if ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == 0 && | 333 | if ((dma_stat & CHECK_DMA_MASK) == 0 && |
334 | (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) == | 334 | (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) == |
335 | (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) | 335 | (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) |
336 | /* INT_IDE lost... bug? */ | 336 | /* INT_IDE lost... bug? */ |
337 | return 0; | 337 | return 0; |
338 | return ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) != | 338 | return ((dma_stat & CHECK_DMA_MASK) != |
339 | ATA_DMA_INTR) ? 0x10 | dma_stat : 0; | 339 | ATA_DMA_INTR) ? 0x10 | dma_stat : 0; |
340 | } | 340 | } |
341 | 341 | ||
@@ -434,97 +434,19 @@ static void tx4939ide_tf_load_fixup(ide_drive_t *drive) | |||
434 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); | 434 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); |
435 | } | 435 | } |
436 | 436 | ||
437 | #ifdef __BIG_ENDIAN | 437 | static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, |
438 | 438 | u8 valid) | |
439 | /* custom iops (independent from SWAP_IO_SPACE) */ | ||
440 | static u8 tx4939ide_inb(unsigned long port) | ||
441 | { | 439 | { |
442 | return __raw_readb((void __iomem *)port); | 440 | ide_tf_load(drive, tf, valid); |
443 | } | ||
444 | 441 | ||
445 | static void tx4939ide_outb(u8 value, unsigned long port) | 442 | if (valid & IDE_VALID_DEVICE) |
446 | { | ||
447 | __raw_writeb(value, (void __iomem *)port); | ||
448 | } | ||
449 | |||
450 | static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | ||
451 | { | ||
452 | ide_hwif_t *hwif = drive->hwif; | ||
453 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
454 | struct ide_taskfile *tf = &cmd->tf; | ||
455 | u8 HIHI = cmd->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF; | ||
456 | |||
457 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | ||
458 | HIHI = 0xFF; | ||
459 | |||
460 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
461 | tx4939ide_outb(tf->hob_feature, io_ports->feature_addr); | ||
462 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
463 | tx4939ide_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
464 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
465 | tx4939ide_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
466 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
467 | tx4939ide_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
468 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
469 | tx4939ide_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
470 | |||
471 | if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
472 | tx4939ide_outb(tf->feature, io_ports->feature_addr); | ||
473 | if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
474 | tx4939ide_outb(tf->nsect, io_ports->nsect_addr); | ||
475 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
476 | tx4939ide_outb(tf->lbal, io_ports->lbal_addr); | ||
477 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
478 | tx4939ide_outb(tf->lbam, io_ports->lbam_addr); | ||
479 | if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
480 | tx4939ide_outb(tf->lbah, io_ports->lbah_addr); | ||
481 | |||
482 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) { | ||
483 | tx4939ide_outb((tf->device & HIHI) | drive->select, | ||
484 | io_ports->device_addr); | ||
485 | tx4939ide_tf_load_fixup(drive); | 443 | tx4939ide_tf_load_fixup(drive); |
486 | } | ||
487 | } | 444 | } |
488 | 445 | ||
489 | static void tx4939ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | 446 | #ifdef __BIG_ENDIAN |
490 | { | ||
491 | ide_hwif_t *hwif = drive->hwif; | ||
492 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
493 | struct ide_taskfile *tf = &cmd->tf; | ||
494 | |||
495 | /* be sure we're looking at the low order bits */ | ||
496 | tx4939ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
497 | |||
498 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) | ||
499 | tf->error = tx4939ide_inb(io_ports->feature_addr); | ||
500 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | ||
501 | tf->nsect = tx4939ide_inb(io_ports->nsect_addr); | ||
502 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | ||
503 | tf->lbal = tx4939ide_inb(io_ports->lbal_addr); | ||
504 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) | ||
505 | tf->lbam = tx4939ide_inb(io_ports->lbam_addr); | ||
506 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) | ||
507 | tf->lbah = tx4939ide_inb(io_ports->lbah_addr); | ||
508 | if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
509 | tf->device = tx4939ide_inb(io_ports->device_addr); | ||
510 | |||
511 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | ||
512 | tx4939ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
513 | |||
514 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) | ||
515 | tf->hob_error = tx4939ide_inb(io_ports->feature_addr); | ||
516 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
517 | tf->hob_nsect = tx4939ide_inb(io_ports->nsect_addr); | ||
518 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
519 | tf->hob_lbal = tx4939ide_inb(io_ports->lbal_addr); | ||
520 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
521 | tf->hob_lbam = tx4939ide_inb(io_ports->lbam_addr); | ||
522 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
523 | tf->hob_lbah = tx4939ide_inb(io_ports->lbah_addr); | ||
524 | } | ||
525 | } | ||
526 | 447 | ||
527 | static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq, | 448 | /* custom iops (independent from SWAP_IO_SPACE) */ |
449 | static void tx4939ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, | ||
528 | void *buf, unsigned int len) | 450 | void *buf, unsigned int len) |
529 | { | 451 | { |
530 | unsigned long port = drive->hwif->io_ports.data_addr; | 452 | unsigned long port = drive->hwif->io_ports.data_addr; |
@@ -536,7 +458,7 @@ static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq, | |||
536 | __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); | 458 | __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); |
537 | } | 459 | } |
538 | 460 | ||
539 | static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq, | 461 | static void tx4939ide_output_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, |
540 | void *buf, unsigned int len) | 462 | void *buf, unsigned int len) |
541 | { | 463 | { |
542 | unsigned long port = drive->hwif->io_ports.data_addr; | 464 | unsigned long port = drive->hwif->io_ports.data_addr; |
@@ -558,7 +480,7 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { | |||
558 | 480 | ||
559 | .dev_select = ide_dev_select, | 481 | .dev_select = ide_dev_select, |
560 | .tf_load = tx4939ide_tf_load, | 482 | .tf_load = tx4939ide_tf_load, |
561 | .tf_read = tx4939ide_tf_read, | 483 | .tf_read = ide_tf_read, |
562 | 484 | ||
563 | .input_data = tx4939ide_input_data_swap, | 485 | .input_data = tx4939ide_input_data_swap, |
564 | .output_data = tx4939ide_output_data_swap, | 486 | .output_data = tx4939ide_output_data_swap, |
@@ -566,14 +488,6 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { | |||
566 | 488 | ||
567 | #else /* __LITTLE_ENDIAN */ | 489 | #else /* __LITTLE_ENDIAN */ |
568 | 490 | ||
569 | static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | ||
570 | { | ||
571 | ide_tf_load(drive, cmd); | ||
572 | |||
573 | if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
574 | tx4939ide_tf_load_fixup(drive); | ||
575 | } | ||
576 | |||
577 | static const struct ide_tp_ops tx4939ide_tp_ops = { | 491 | static const struct ide_tp_ops tx4939ide_tp_ops = { |
578 | .exec_command = ide_exec_command, | 492 | .exec_command = ide_exec_command, |
579 | .read_status = ide_read_status, | 493 | .read_status = ide_read_status, |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 2a2e50871b40..851de83ff455 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -297,21 +297,25 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv) | |||
297 | id_priv->cma_dev = NULL; | 297 | id_priv->cma_dev = NULL; |
298 | } | 298 | } |
299 | 299 | ||
300 | static int cma_set_qkey(struct ib_device *device, u8 port_num, | 300 | static int cma_set_qkey(struct rdma_id_private *id_priv) |
301 | enum rdma_port_space ps, | ||
302 | struct rdma_dev_addr *dev_addr, u32 *qkey) | ||
303 | { | 301 | { |
304 | struct ib_sa_mcmember_rec rec; | 302 | struct ib_sa_mcmember_rec rec; |
305 | int ret = 0; | 303 | int ret = 0; |
306 | 304 | ||
307 | switch (ps) { | 305 | if (id_priv->qkey) |
306 | return 0; | ||
307 | |||
308 | switch (id_priv->id.ps) { | ||
308 | case RDMA_PS_UDP: | 309 | case RDMA_PS_UDP: |
309 | *qkey = RDMA_UDP_QKEY; | 310 | id_priv->qkey = RDMA_UDP_QKEY; |
310 | break; | 311 | break; |
311 | case RDMA_PS_IPOIB: | 312 | case RDMA_PS_IPOIB: |
312 | ib_addr_get_mgid(dev_addr, &rec.mgid); | 313 | ib_addr_get_mgid(&id_priv->id.route.addr.dev_addr, &rec.mgid); |
313 | ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec); | 314 | ret = ib_sa_get_mcmember_rec(id_priv->id.device, |
314 | *qkey = be32_to_cpu(rec.qkey); | 315 | id_priv->id.port_num, &rec.mgid, |
316 | &rec); | ||
317 | if (!ret) | ||
318 | id_priv->qkey = be32_to_cpu(rec.qkey); | ||
315 | break; | 319 | break; |
316 | default: | 320 | default: |
317 | break; | 321 | break; |
@@ -341,12 +345,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) | |||
341 | ret = ib_find_cached_gid(cma_dev->device, &gid, | 345 | ret = ib_find_cached_gid(cma_dev->device, &gid, |
342 | &id_priv->id.port_num, NULL); | 346 | &id_priv->id.port_num, NULL); |
343 | if (!ret) { | 347 | if (!ret) { |
344 | ret = cma_set_qkey(cma_dev->device, | 348 | cma_attach_to_dev(id_priv, cma_dev); |
345 | id_priv->id.port_num, | ||
346 | id_priv->id.ps, dev_addr, | ||
347 | &id_priv->qkey); | ||
348 | if (!ret) | ||
349 | cma_attach_to_dev(id_priv, cma_dev); | ||
350 | break; | 349 | break; |
351 | } | 350 | } |
352 | } | 351 | } |
@@ -578,6 +577,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv, | |||
578 | *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT; | 577 | *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT; |
579 | 578 | ||
580 | if (cma_is_ud_ps(id_priv->id.ps)) { | 579 | if (cma_is_ud_ps(id_priv->id.ps)) { |
580 | ret = cma_set_qkey(id_priv); | ||
581 | if (ret) | ||
582 | return ret; | ||
583 | |||
581 | qp_attr->qkey = id_priv->qkey; | 584 | qp_attr->qkey = id_priv->qkey; |
582 | *qp_attr_mask |= IB_QP_QKEY; | 585 | *qp_attr_mask |= IB_QP_QKEY; |
583 | } else { | 586 | } else { |
@@ -2201,6 +2204,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, | |||
2201 | event.status = ib_event->param.sidr_rep_rcvd.status; | 2204 | event.status = ib_event->param.sidr_rep_rcvd.status; |
2202 | break; | 2205 | break; |
2203 | } | 2206 | } |
2207 | ret = cma_set_qkey(id_priv); | ||
2208 | if (ret) { | ||
2209 | event.event = RDMA_CM_EVENT_ADDR_ERROR; | ||
2210 | event.status = -EINVAL; | ||
2211 | break; | ||
2212 | } | ||
2204 | if (id_priv->qkey != rep->qkey) { | 2213 | if (id_priv->qkey != rep->qkey) { |
2205 | event.event = RDMA_CM_EVENT_UNREACHABLE; | 2214 | event.event = RDMA_CM_EVENT_UNREACHABLE; |
2206 | event.status = -EINVAL; | 2215 | event.status = -EINVAL; |
@@ -2480,10 +2489,14 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv, | |||
2480 | const void *private_data, int private_data_len) | 2489 | const void *private_data, int private_data_len) |
2481 | { | 2490 | { |
2482 | struct ib_cm_sidr_rep_param rep; | 2491 | struct ib_cm_sidr_rep_param rep; |
2492 | int ret; | ||
2483 | 2493 | ||
2484 | memset(&rep, 0, sizeof rep); | 2494 | memset(&rep, 0, sizeof rep); |
2485 | rep.status = status; | 2495 | rep.status = status; |
2486 | if (status == IB_SIDR_SUCCESS) { | 2496 | if (status == IB_SIDR_SUCCESS) { |
2497 | ret = cma_set_qkey(id_priv); | ||
2498 | if (ret) | ||
2499 | return ret; | ||
2487 | rep.qp_num = id_priv->qp_num; | 2500 | rep.qp_num = id_priv->qp_num; |
2488 | rep.qkey = id_priv->qkey; | 2501 | rep.qkey = id_priv->qkey; |
2489 | } | 2502 | } |
@@ -2713,6 +2726,10 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv, | |||
2713 | IB_SA_MCMEMBER_REC_FLOW_LABEL | | 2726 | IB_SA_MCMEMBER_REC_FLOW_LABEL | |
2714 | IB_SA_MCMEMBER_REC_TRAFFIC_CLASS; | 2727 | IB_SA_MCMEMBER_REC_TRAFFIC_CLASS; |
2715 | 2728 | ||
2729 | if (id_priv->id.ps == RDMA_PS_IPOIB) | ||
2730 | comp_mask |= IB_SA_MCMEMBER_REC_RATE | | ||
2731 | IB_SA_MCMEMBER_REC_RATE_SELECTOR; | ||
2732 | |||
2716 | mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device, | 2733 | mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device, |
2717 | id_priv->id.port_num, &rec, | 2734 | id_priv->id.port_num, &rec, |
2718 | comp_mask, GFP_KERNEL, | 2735 | comp_mask, GFP_KERNEL, |
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index a4a82bff7100..8d71086f5a1c 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c | |||
@@ -152,7 +152,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid) | |||
152 | sge_cmd = qpid << 8 | 3; | 152 | sge_cmd = qpid << 8 | 3; |
153 | wqe->sge_cmd = cpu_to_be64(sge_cmd); | 153 | wqe->sge_cmd = cpu_to_be64(sge_cmd); |
154 | skb->priority = CPL_PRIORITY_CONTROL; | 154 | skb->priority = CPL_PRIORITY_CONTROL; |
155 | return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb)); | 155 | return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb); |
156 | } | 156 | } |
157 | 157 | ||
158 | int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq) | 158 | int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq) |
@@ -571,7 +571,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p) | |||
571 | (unsigned long long) rdev_p->ctrl_qp.dma_addr, | 571 | (unsigned long long) rdev_p->ctrl_qp.dma_addr, |
572 | rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2); | 572 | rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2); |
573 | skb->priority = CPL_PRIORITY_CONTROL; | 573 | skb->priority = CPL_PRIORITY_CONTROL; |
574 | return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb)); | 574 | return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb); |
575 | err: | 575 | err: |
576 | kfree_skb(skb); | 576 | kfree_skb(skb); |
577 | return err; | 577 | return err; |
@@ -701,7 +701,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry, | |||
701 | u32 stag_idx; | 701 | u32 stag_idx; |
702 | u32 wptr; | 702 | u32 wptr; |
703 | 703 | ||
704 | if (rdev_p->flags) | 704 | if (cxio_fatal_error(rdev_p)) |
705 | return -EIO; | 705 | return -EIO; |
706 | 706 | ||
707 | stag_state = stag_state > 0; | 707 | stag_state = stag_state > 0; |
@@ -858,7 +858,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr) | |||
858 | wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size); | 858 | wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size); |
859 | wqe->irs = cpu_to_be32(attr->irs); | 859 | wqe->irs = cpu_to_be32(attr->irs); |
860 | skb->priority = 0; /* 0=>ToeQ; 1=>CtrlQ */ | 860 | skb->priority = 0; /* 0=>ToeQ; 1=>CtrlQ */ |
861 | return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb)); | 861 | return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb); |
862 | } | 862 | } |
863 | 863 | ||
864 | void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb) | 864 | void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb) |
@@ -1041,9 +1041,9 @@ void cxio_rdev_close(struct cxio_rdev *rdev_p) | |||
1041 | cxio_hal_pblpool_destroy(rdev_p); | 1041 | cxio_hal_pblpool_destroy(rdev_p); |
1042 | cxio_hal_rqtpool_destroy(rdev_p); | 1042 | cxio_hal_rqtpool_destroy(rdev_p); |
1043 | list_del(&rdev_p->entry); | 1043 | list_del(&rdev_p->entry); |
1044 | rdev_p->t3cdev_p->ulp = NULL; | ||
1045 | cxio_hal_destroy_ctrl_qp(rdev_p); | 1044 | cxio_hal_destroy_ctrl_qp(rdev_p); |
1046 | cxio_hal_destroy_resource(rdev_p->rscp); | 1045 | cxio_hal_destroy_resource(rdev_p->rscp); |
1046 | rdev_p->t3cdev_p->ulp = NULL; | ||
1047 | } | 1047 | } |
1048 | } | 1048 | } |
1049 | 1049 | ||
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 094a66d1480c..bfd03bf8be54 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h | |||
@@ -115,6 +115,11 @@ struct cxio_rdev { | |||
115 | #define CXIO_ERROR_FATAL 1 | 115 | #define CXIO_ERROR_FATAL 1 |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static inline int cxio_fatal_error(struct cxio_rdev *rdev_p) | ||
119 | { | ||
120 | return rdev_p->flags & CXIO_ERROR_FATAL; | ||
121 | } | ||
122 | |||
118 | static inline int cxio_num_stags(struct cxio_rdev *rdev_p) | 123 | static inline int cxio_num_stags(struct cxio_rdev *rdev_p) |
119 | { | 124 | { |
120 | return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5)); | 125 | return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5)); |
@@ -188,6 +193,7 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count); | |||
188 | void cxio_flush_hw_cq(struct t3_cq *cq); | 193 | void cxio_flush_hw_cq(struct t3_cq *cq); |
189 | int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe, | 194 | int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe, |
190 | u8 *cqe_flushed, u64 *cookie, u32 *credit); | 195 | u8 *cqe_flushed, u64 *cookie, u32 *credit); |
196 | int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb); | ||
191 | 197 | ||
192 | #define MOD "iw_cxgb3: " | 198 | #define MOD "iw_cxgb3: " |
193 | #define PDBG(fmt, args...) pr_debug(MOD fmt, ## args) | 199 | #define PDBG(fmt, args...) pr_debug(MOD fmt, ## args) |
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c index 37a4fc264a07..26fc0a4eaa74 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.c +++ b/drivers/infiniband/hw/cxgb3/iwch.c | |||
@@ -165,12 +165,19 @@ static void close_rnic_dev(struct t3cdev *tdev) | |||
165 | static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error) | 165 | static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error) |
166 | { | 166 | { |
167 | struct cxio_rdev *rdev = tdev->ulp; | 167 | struct cxio_rdev *rdev = tdev->ulp; |
168 | struct iwch_dev *rnicp = rdev_to_iwch_dev(rdev); | ||
169 | struct ib_event event; | ||
168 | 170 | ||
169 | if (status == OFFLOAD_STATUS_DOWN) | 171 | if (status == OFFLOAD_STATUS_DOWN) { |
170 | rdev->flags = CXIO_ERROR_FATAL; | 172 | rdev->flags = CXIO_ERROR_FATAL; |
171 | 173 | ||
172 | return; | 174 | event.device = &rnicp->ibdev; |
175 | event.event = IB_EVENT_DEVICE_FATAL; | ||
176 | event.element.port_num = 0; | ||
177 | ib_dispatch_event(&event); | ||
178 | } | ||
173 | 179 | ||
180 | return; | ||
174 | } | 181 | } |
175 | 182 | ||
176 | static int __init iwch_init_module(void) | 183 | static int __init iwch_init_module(void) |
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h index 3773453b2cf0..84735506333f 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.h +++ b/drivers/infiniband/hw/cxgb3/iwch.h | |||
@@ -117,6 +117,11 @@ static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev) | |||
117 | return container_of(ibdev, struct iwch_dev, ibdev); | 117 | return container_of(ibdev, struct iwch_dev, ibdev); |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline struct iwch_dev *rdev_to_iwch_dev(struct cxio_rdev *rdev) | ||
121 | { | ||
122 | return container_of(rdev, struct iwch_dev, rdev); | ||
123 | } | ||
124 | |||
120 | static inline int t3b_device(const struct iwch_dev *rhp) | 125 | static inline int t3b_device(const struct iwch_dev *rhp) |
121 | { | 126 | { |
122 | return rhp->rdev.t3cdev_p->type == T3B; | 127 | return rhp->rdev.t3cdev_p->type == T3B; |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 8699947aaf6c..fef3f1ae7225 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c | |||
@@ -139,6 +139,38 @@ static void stop_ep_timer(struct iwch_ep *ep) | |||
139 | put_ep(&ep->com); | 139 | put_ep(&ep->com); |
140 | } | 140 | } |
141 | 141 | ||
142 | int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2e) | ||
143 | { | ||
144 | int error = 0; | ||
145 | struct cxio_rdev *rdev; | ||
146 | |||
147 | rdev = (struct cxio_rdev *)tdev->ulp; | ||
148 | if (cxio_fatal_error(rdev)) { | ||
149 | kfree_skb(skb); | ||
150 | return -EIO; | ||
151 | } | ||
152 | error = l2t_send(tdev, skb, l2e); | ||
153 | if (error) | ||
154 | kfree_skb(skb); | ||
155 | return error; | ||
156 | } | ||
157 | |||
158 | int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb) | ||
159 | { | ||
160 | int error = 0; | ||
161 | struct cxio_rdev *rdev; | ||
162 | |||
163 | rdev = (struct cxio_rdev *)tdev->ulp; | ||
164 | if (cxio_fatal_error(rdev)) { | ||
165 | kfree_skb(skb); | ||
166 | return -EIO; | ||
167 | } | ||
168 | error = cxgb3_ofld_send(tdev, skb); | ||
169 | if (error) | ||
170 | kfree_skb(skb); | ||
171 | return error; | ||
172 | } | ||
173 | |||
142 | static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb) | 174 | static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb) |
143 | { | 175 | { |
144 | struct cpl_tid_release *req; | 176 | struct cpl_tid_release *req; |
@@ -150,7 +182,7 @@ static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb) | |||
150 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 182 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
151 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid)); | 183 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid)); |
152 | skb->priority = CPL_PRIORITY_SETUP; | 184 | skb->priority = CPL_PRIORITY_SETUP; |
153 | cxgb3_ofld_send(tdev, skb); | 185 | iwch_cxgb3_ofld_send(tdev, skb); |
154 | return; | 186 | return; |
155 | } | 187 | } |
156 | 188 | ||
@@ -172,8 +204,7 @@ int iwch_quiesce_tid(struct iwch_ep *ep) | |||
172 | req->val = cpu_to_be64(1 << S_TCB_RX_QUIESCE); | 204 | req->val = cpu_to_be64(1 << S_TCB_RX_QUIESCE); |
173 | 205 | ||
174 | skb->priority = CPL_PRIORITY_DATA; | 206 | skb->priority = CPL_PRIORITY_DATA; |
175 | cxgb3_ofld_send(ep->com.tdev, skb); | 207 | return iwch_cxgb3_ofld_send(ep->com.tdev, skb); |
176 | return 0; | ||
177 | } | 208 | } |
178 | 209 | ||
179 | int iwch_resume_tid(struct iwch_ep *ep) | 210 | int iwch_resume_tid(struct iwch_ep *ep) |
@@ -194,8 +225,7 @@ int iwch_resume_tid(struct iwch_ep *ep) | |||
194 | req->val = 0; | 225 | req->val = 0; |
195 | 226 | ||
196 | skb->priority = CPL_PRIORITY_DATA; | 227 | skb->priority = CPL_PRIORITY_DATA; |
197 | cxgb3_ofld_send(ep->com.tdev, skb); | 228 | return iwch_cxgb3_ofld_send(ep->com.tdev, skb); |
198 | return 0; | ||
199 | } | 229 | } |
200 | 230 | ||
201 | static void set_emss(struct iwch_ep *ep, u16 opt) | 231 | static void set_emss(struct iwch_ep *ep, u16 opt) |
@@ -252,18 +282,22 @@ static void *alloc_ep(int size, gfp_t gfp) | |||
252 | 282 | ||
253 | void __free_ep(struct kref *kref) | 283 | void __free_ep(struct kref *kref) |
254 | { | 284 | { |
255 | struct iwch_ep_common *epc; | 285 | struct iwch_ep *ep; |
256 | epc = container_of(kref, struct iwch_ep_common, kref); | 286 | ep = container_of(container_of(kref, struct iwch_ep_common, kref), |
257 | PDBG("%s ep %p state %s\n", __func__, epc, states[state_read(epc)]); | 287 | struct iwch_ep, com); |
258 | kfree(epc); | 288 | PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]); |
289 | if (ep->com.flags & RELEASE_RESOURCES) { | ||
290 | cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid); | ||
291 | dst_release(ep->dst); | ||
292 | l2t_release(L2DATA(ep->com.tdev), ep->l2t); | ||
293 | } | ||
294 | kfree(ep); | ||
259 | } | 295 | } |
260 | 296 | ||
261 | static void release_ep_resources(struct iwch_ep *ep) | 297 | static void release_ep_resources(struct iwch_ep *ep) |
262 | { | 298 | { |
263 | PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); | 299 | PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); |
264 | cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid); | 300 | ep->com.flags |= RELEASE_RESOURCES; |
265 | dst_release(ep->dst); | ||
266 | l2t_release(L2DATA(ep->com.tdev), ep->l2t); | ||
267 | put_ep(&ep->com); | 301 | put_ep(&ep->com); |
268 | } | 302 | } |
269 | 303 | ||
@@ -382,7 +416,7 @@ static void abort_arp_failure(struct t3cdev *dev, struct sk_buff *skb) | |||
382 | 416 | ||
383 | PDBG("%s t3cdev %p\n", __func__, dev); | 417 | PDBG("%s t3cdev %p\n", __func__, dev); |
384 | req->cmd = CPL_ABORT_NO_RST; | 418 | req->cmd = CPL_ABORT_NO_RST; |
385 | cxgb3_ofld_send(dev, skb); | 419 | iwch_cxgb3_ofld_send(dev, skb); |
386 | } | 420 | } |
387 | 421 | ||
388 | static int send_halfclose(struct iwch_ep *ep, gfp_t gfp) | 422 | static int send_halfclose(struct iwch_ep *ep, gfp_t gfp) |
@@ -402,8 +436,7 @@ static int send_halfclose(struct iwch_ep *ep, gfp_t gfp) | |||
402 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON)); | 436 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON)); |
403 | req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); | 437 | req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); |
404 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, ep->hwtid)); | 438 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, ep->hwtid)); |
405 | l2t_send(ep->com.tdev, skb, ep->l2t); | 439 | return iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
406 | return 0; | ||
407 | } | 440 | } |
408 | 441 | ||
409 | static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp) | 442 | static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp) |
@@ -424,8 +457,7 @@ static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp) | |||
424 | req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); | 457 | req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); |
425 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid)); | 458 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid)); |
426 | req->cmd = CPL_ABORT_SEND_RST; | 459 | req->cmd = CPL_ABORT_SEND_RST; |
427 | l2t_send(ep->com.tdev, skb, ep->l2t); | 460 | return iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
428 | return 0; | ||
429 | } | 461 | } |
430 | 462 | ||
431 | static int send_connect(struct iwch_ep *ep) | 463 | static int send_connect(struct iwch_ep *ep) |
@@ -469,8 +501,7 @@ static int send_connect(struct iwch_ep *ep) | |||
469 | req->opt0l = htonl(opt0l); | 501 | req->opt0l = htonl(opt0l); |
470 | req->params = 0; | 502 | req->params = 0; |
471 | req->opt2 = htonl(opt2); | 503 | req->opt2 = htonl(opt2); |
472 | l2t_send(ep->com.tdev, skb, ep->l2t); | 504 | return iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
473 | return 0; | ||
474 | } | 505 | } |
475 | 506 | ||
476 | static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb) | 507 | static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb) |
@@ -527,7 +558,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb) | |||
527 | req->sndseq = htonl(ep->snd_seq); | 558 | req->sndseq = htonl(ep->snd_seq); |
528 | BUG_ON(ep->mpa_skb); | 559 | BUG_ON(ep->mpa_skb); |
529 | ep->mpa_skb = skb; | 560 | ep->mpa_skb = skb; |
530 | l2t_send(ep->com.tdev, skb, ep->l2t); | 561 | iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
531 | start_ep_timer(ep); | 562 | start_ep_timer(ep); |
532 | state_set(&ep->com, MPA_REQ_SENT); | 563 | state_set(&ep->com, MPA_REQ_SENT); |
533 | return; | 564 | return; |
@@ -578,8 +609,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen) | |||
578 | req->sndseq = htonl(ep->snd_seq); | 609 | req->sndseq = htonl(ep->snd_seq); |
579 | BUG_ON(ep->mpa_skb); | 610 | BUG_ON(ep->mpa_skb); |
580 | ep->mpa_skb = skb; | 611 | ep->mpa_skb = skb; |
581 | l2t_send(ep->com.tdev, skb, ep->l2t); | 612 | return iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
582 | return 0; | ||
583 | } | 613 | } |
584 | 614 | ||
585 | static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen) | 615 | static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen) |
@@ -630,8 +660,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen) | |||
630 | req->sndseq = htonl(ep->snd_seq); | 660 | req->sndseq = htonl(ep->snd_seq); |
631 | ep->mpa_skb = skb; | 661 | ep->mpa_skb = skb; |
632 | state_set(&ep->com, MPA_REP_SENT); | 662 | state_set(&ep->com, MPA_REP_SENT); |
633 | l2t_send(ep->com.tdev, skb, ep->l2t); | 663 | return iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
634 | return 0; | ||
635 | } | 664 | } |
636 | 665 | ||
637 | static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | 666 | static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) |
@@ -795,7 +824,7 @@ static int update_rx_credits(struct iwch_ep *ep, u32 credits) | |||
795 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, ep->hwtid)); | 824 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, ep->hwtid)); |
796 | req->credit_dack = htonl(V_RX_CREDITS(credits) | V_RX_FORCE_ACK(1)); | 825 | req->credit_dack = htonl(V_RX_CREDITS(credits) | V_RX_FORCE_ACK(1)); |
797 | skb->priority = CPL_PRIORITY_ACK; | 826 | skb->priority = CPL_PRIORITY_ACK; |
798 | cxgb3_ofld_send(ep->com.tdev, skb); | 827 | iwch_cxgb3_ofld_send(ep->com.tdev, skb); |
799 | return credits; | 828 | return credits; |
800 | } | 829 | } |
801 | 830 | ||
@@ -1127,8 +1156,8 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | |||
1127 | * We get 2 abort replies from the HW. The first one must | 1156 | * We get 2 abort replies from the HW. The first one must |
1128 | * be ignored except for scribbling that we need one more. | 1157 | * be ignored except for scribbling that we need one more. |
1129 | */ | 1158 | */ |
1130 | if (!(ep->flags & ABORT_REQ_IN_PROGRESS)) { | 1159 | if (!(ep->com.flags & ABORT_REQ_IN_PROGRESS)) { |
1131 | ep->flags |= ABORT_REQ_IN_PROGRESS; | 1160 | ep->com.flags |= ABORT_REQ_IN_PROGRESS; |
1132 | return CPL_RET_BUF_DONE; | 1161 | return CPL_RET_BUF_DONE; |
1133 | } | 1162 | } |
1134 | 1163 | ||
@@ -1203,8 +1232,7 @@ static int listen_start(struct iwch_listen_ep *ep) | |||
1203 | req->opt1 = htonl(V_CONN_POLICY(CPL_CONN_POLICY_ASK)); | 1232 | req->opt1 = htonl(V_CONN_POLICY(CPL_CONN_POLICY_ASK)); |
1204 | 1233 | ||
1205 | skb->priority = 1; | 1234 | skb->priority = 1; |
1206 | cxgb3_ofld_send(ep->com.tdev, skb); | 1235 | return iwch_cxgb3_ofld_send(ep->com.tdev, skb); |
1207 | return 0; | ||
1208 | } | 1236 | } |
1209 | 1237 | ||
1210 | static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | 1238 | static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) |
@@ -1237,8 +1265,7 @@ static int listen_stop(struct iwch_listen_ep *ep) | |||
1237 | req->cpu_idx = 0; | 1265 | req->cpu_idx = 0; |
1238 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid)); | 1266 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid)); |
1239 | skb->priority = 1; | 1267 | skb->priority = 1; |
1240 | cxgb3_ofld_send(ep->com.tdev, skb); | 1268 | return iwch_cxgb3_ofld_send(ep->com.tdev, skb); |
1241 | return 0; | ||
1242 | } | 1269 | } |
1243 | 1270 | ||
1244 | static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb, | 1271 | static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb, |
@@ -1286,7 +1313,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb) | |||
1286 | rpl->opt2 = htonl(opt2); | 1313 | rpl->opt2 = htonl(opt2); |
1287 | rpl->rsvd = rpl->opt2; /* workaround for HW bug */ | 1314 | rpl->rsvd = rpl->opt2; /* workaround for HW bug */ |
1288 | skb->priority = CPL_PRIORITY_SETUP; | 1315 | skb->priority = CPL_PRIORITY_SETUP; |
1289 | l2t_send(ep->com.tdev, skb, ep->l2t); | 1316 | iwch_l2t_send(ep->com.tdev, skb, ep->l2t); |
1290 | 1317 | ||
1291 | return; | 1318 | return; |
1292 | } | 1319 | } |
@@ -1315,7 +1342,7 @@ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip, | |||
1315 | rpl->opt0l_status = htonl(CPL_PASS_OPEN_REJECT); | 1342 | rpl->opt0l_status = htonl(CPL_PASS_OPEN_REJECT); |
1316 | rpl->opt2 = 0; | 1343 | rpl->opt2 = 0; |
1317 | rpl->rsvd = rpl->opt2; | 1344 | rpl->rsvd = rpl->opt2; |
1318 | cxgb3_ofld_send(tdev, skb); | 1345 | iwch_cxgb3_ofld_send(tdev, skb); |
1319 | } | 1346 | } |
1320 | } | 1347 | } |
1321 | 1348 | ||
@@ -1534,8 +1561,8 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | |||
1534 | * We get 2 peer aborts from the HW. The first one must | 1561 | * We get 2 peer aborts from the HW. The first one must |
1535 | * be ignored except for scribbling that we need one more. | 1562 | * be ignored except for scribbling that we need one more. |
1536 | */ | 1563 | */ |
1537 | if (!(ep->flags & PEER_ABORT_IN_PROGRESS)) { | 1564 | if (!(ep->com.flags & PEER_ABORT_IN_PROGRESS)) { |
1538 | ep->flags |= PEER_ABORT_IN_PROGRESS; | 1565 | ep->com.flags |= PEER_ABORT_IN_PROGRESS; |
1539 | return CPL_RET_BUF_DONE; | 1566 | return CPL_RET_BUF_DONE; |
1540 | } | 1567 | } |
1541 | 1568 | ||
@@ -1613,7 +1640,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | |||
1613 | rpl->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); | 1640 | rpl->wr.wr_lo = htonl(V_WR_TID(ep->hwtid)); |
1614 | OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); | 1641 | OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); |
1615 | rpl->cmd = CPL_ABORT_NO_RST; | 1642 | rpl->cmd = CPL_ABORT_NO_RST; |
1616 | cxgb3_ofld_send(ep->com.tdev, rpl_skb); | 1643 | iwch_cxgb3_ofld_send(ep->com.tdev, rpl_skb); |
1617 | out: | 1644 | out: |
1618 | if (release) | 1645 | if (release) |
1619 | release_ep_resources(ep); | 1646 | release_ep_resources(ep); |
@@ -2017,8 +2044,11 @@ int iwch_destroy_listen(struct iw_cm_id *cm_id) | |||
2017 | ep->com.rpl_done = 0; | 2044 | ep->com.rpl_done = 0; |
2018 | ep->com.rpl_err = 0; | 2045 | ep->com.rpl_err = 0; |
2019 | err = listen_stop(ep); | 2046 | err = listen_stop(ep); |
2047 | if (err) | ||
2048 | goto done; | ||
2020 | wait_event(ep->com.waitq, ep->com.rpl_done); | 2049 | wait_event(ep->com.waitq, ep->com.rpl_done); |
2021 | cxgb3_free_stid(ep->com.tdev, ep->stid); | 2050 | cxgb3_free_stid(ep->com.tdev, ep->stid); |
2051 | done: | ||
2022 | err = ep->com.rpl_err; | 2052 | err = ep->com.rpl_err; |
2023 | cm_id->rem_ref(cm_id); | 2053 | cm_id->rem_ref(cm_id); |
2024 | put_ep(&ep->com); | 2054 | put_ep(&ep->com); |
@@ -2030,12 +2060,22 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp) | |||
2030 | int ret=0; | 2060 | int ret=0; |
2031 | unsigned long flags; | 2061 | unsigned long flags; |
2032 | int close = 0; | 2062 | int close = 0; |
2063 | int fatal = 0; | ||
2064 | struct t3cdev *tdev; | ||
2065 | struct cxio_rdev *rdev; | ||
2033 | 2066 | ||
2034 | spin_lock_irqsave(&ep->com.lock, flags); | 2067 | spin_lock_irqsave(&ep->com.lock, flags); |
2035 | 2068 | ||
2036 | PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, | 2069 | PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, |
2037 | states[ep->com.state], abrupt); | 2070 | states[ep->com.state], abrupt); |
2038 | 2071 | ||
2072 | tdev = (struct t3cdev *)ep->com.tdev; | ||
2073 | rdev = (struct cxio_rdev *)tdev->ulp; | ||
2074 | if (cxio_fatal_error(rdev)) { | ||
2075 | fatal = 1; | ||
2076 | close_complete_upcall(ep); | ||
2077 | ep->com.state = DEAD; | ||
2078 | } | ||
2039 | switch (ep->com.state) { | 2079 | switch (ep->com.state) { |
2040 | case MPA_REQ_WAIT: | 2080 | case MPA_REQ_WAIT: |
2041 | case MPA_REQ_SENT: | 2081 | case MPA_REQ_SENT: |
@@ -2075,7 +2115,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp) | |||
2075 | ret = send_abort(ep, NULL, gfp); | 2115 | ret = send_abort(ep, NULL, gfp); |
2076 | else | 2116 | else |
2077 | ret = send_halfclose(ep, gfp); | 2117 | ret = send_halfclose(ep, gfp); |
2118 | if (ret) | ||
2119 | fatal = 1; | ||
2078 | } | 2120 | } |
2121 | if (fatal) | ||
2122 | release_ep_resources(ep); | ||
2079 | return ret; | 2123 | return ret; |
2080 | } | 2124 | } |
2081 | 2125 | ||
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h index d7c7e09f0996..43c0aea7eadc 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.h +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h | |||
@@ -147,6 +147,7 @@ enum iwch_ep_state { | |||
147 | enum iwch_ep_flags { | 147 | enum iwch_ep_flags { |
148 | PEER_ABORT_IN_PROGRESS = (1 << 0), | 148 | PEER_ABORT_IN_PROGRESS = (1 << 0), |
149 | ABORT_REQ_IN_PROGRESS = (1 << 1), | 149 | ABORT_REQ_IN_PROGRESS = (1 << 1), |
150 | RELEASE_RESOURCES = (1 << 2), | ||
150 | }; | 151 | }; |
151 | 152 | ||
152 | struct iwch_ep_common { | 153 | struct iwch_ep_common { |
@@ -161,6 +162,7 @@ struct iwch_ep_common { | |||
161 | wait_queue_head_t waitq; | 162 | wait_queue_head_t waitq; |
162 | int rpl_done; | 163 | int rpl_done; |
163 | int rpl_err; | 164 | int rpl_err; |
165 | u32 flags; | ||
164 | }; | 166 | }; |
165 | 167 | ||
166 | struct iwch_listen_ep { | 168 | struct iwch_listen_ep { |
@@ -188,7 +190,6 @@ struct iwch_ep { | |||
188 | u16 plen; | 190 | u16 plen; |
189 | u32 ird; | 191 | u32 ird; |
190 | u32 ord; | 192 | u32 ord; |
191 | u32 flags; | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id) | 195 | static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id) |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index c758fbd58478..2f546a625330 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
@@ -751,7 +751,7 @@ int iwch_post_zb_read(struct iwch_qp *qhp) | |||
751 | wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)| | 751 | wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)| |
752 | V_FW_RIWR_LEN(flit_cnt)); | 752 | V_FW_RIWR_LEN(flit_cnt)); |
753 | skb->priority = CPL_PRIORITY_DATA; | 753 | skb->priority = CPL_PRIORITY_DATA; |
754 | return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); | 754 | return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); |
755 | } | 755 | } |
756 | 756 | ||
757 | /* | 757 | /* |
@@ -783,7 +783,7 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg) | |||
783 | V_FW_RIWR_FLAGS(T3_COMPLETION_FLAG | T3_NOTIFY_FLAG)); | 783 | V_FW_RIWR_FLAGS(T3_COMPLETION_FLAG | T3_NOTIFY_FLAG)); |
784 | wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)); | 784 | wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)); |
785 | skb->priority = CPL_PRIORITY_DATA; | 785 | skb->priority = CPL_PRIORITY_DATA; |
786 | return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); | 786 | return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); |
787 | } | 787 | } |
788 | 788 | ||
789 | /* | 789 | /* |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 2ccb9d31771f..ae3d7590346e 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -394,8 +394,7 @@ static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
394 | PAGE_SIZE, vma->vm_page_prot)) | 394 | PAGE_SIZE, vma->vm_page_prot)) |
395 | return -EAGAIN; | 395 | return -EAGAIN; |
396 | } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) { | 396 | } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) { |
397 | /* FIXME want pgprot_writecombine() for BlueFlame pages */ | 397 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
398 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
399 | 398 | ||
400 | if (io_remap_pfn_range(vma, vma->vm_start, | 399 | if (io_remap_pfn_range(vma, vma->vm_start, |
401 | to_mucontext(context)->uar.pfn + | 400 | to_mucontext(context)->uar.pfn + |
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 04b12ad23390..17621de54a9f 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
@@ -289,8 +289,8 @@ static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad) | |||
289 | static inline void | 289 | static inline void |
290 | set_wqe_64bit_value(__le32 *wqe_words, u32 index, u64 value) | 290 | set_wqe_64bit_value(__le32 *wqe_words, u32 index, u64 value) |
291 | { | 291 | { |
292 | wqe_words[index] = cpu_to_le32((u32) ((unsigned long)value)); | 292 | wqe_words[index] = cpu_to_le32((u32) value); |
293 | wqe_words[index + 1] = cpu_to_le32((u32)(upper_32_bits((unsigned long)value))); | 293 | wqe_words[index + 1] = cpu_to_le32(upper_32_bits(value)); |
294 | } | 294 | } |
295 | 295 | ||
296 | static inline void | 296 | static inline void |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 52425154acd4..dbd9a75474e3 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -426,6 +426,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
426 | if (type == NES_TIMER_TYPE_CLOSE) { | 426 | if (type == NES_TIMER_TYPE_CLOSE) { |
427 | new_send->timetosend += (HZ/10); | 427 | new_send->timetosend += (HZ/10); |
428 | if (cm_node->recv_entry) { | 428 | if (cm_node->recv_entry) { |
429 | kfree(new_send); | ||
429 | WARN_ON(1); | 430 | WARN_ON(1); |
430 | return -EINVAL; | 431 | return -EINVAL; |
431 | } | 432 | } |
@@ -445,8 +446,8 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
445 | if (ret != NETDEV_TX_OK) { | 446 | if (ret != NETDEV_TX_OK) { |
446 | nes_debug(NES_DBG_CM, "Error sending packet %p " | 447 | nes_debug(NES_DBG_CM, "Error sending packet %p " |
447 | "(jiffies = %lu)\n", new_send, jiffies); | 448 | "(jiffies = %lu)\n", new_send, jiffies); |
448 | atomic_dec(&new_send->skb->users); | ||
449 | new_send->timetosend = jiffies; | 449 | new_send->timetosend = jiffies; |
450 | ret = NETDEV_TX_OK; | ||
450 | } else { | 451 | } else { |
451 | cm_packets_sent++; | 452 | cm_packets_sent++; |
452 | if (!send_retrans) { | 453 | if (!send_retrans) { |
@@ -630,7 +631,6 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
630 | nes_debug(NES_DBG_CM, "rexmit failed for " | 631 | nes_debug(NES_DBG_CM, "rexmit failed for " |
631 | "node=%p\n", cm_node); | 632 | "node=%p\n", cm_node); |
632 | cm_packets_bounced++; | 633 | cm_packets_bounced++; |
633 | atomic_dec(&send_entry->skb->users); | ||
634 | send_entry->retrycount--; | 634 | send_entry->retrycount--; |
635 | nexttimeout = jiffies + NES_SHORT_TIME; | 635 | nexttimeout = jiffies + NES_SHORT_TIME; |
636 | settimer = 1; | 636 | settimer = 1; |
@@ -666,11 +666,6 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
666 | 666 | ||
667 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 667 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); |
668 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 668 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
669 | if (ret != NETDEV_TX_OK) { | ||
670 | nes_debug(NES_DBG_CM, "rexmit failed for cm_node=%p\n", | ||
671 | cm_node); | ||
672 | break; | ||
673 | } | ||
674 | } | 669 | } |
675 | 670 | ||
676 | if (settimer) { | 671 | if (settimer) { |
@@ -1262,7 +1257,6 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1262 | cm_node->nesqp = NULL; | 1257 | cm_node->nesqp = NULL; |
1263 | } | 1258 | } |
1264 | 1259 | ||
1265 | cm_node->freed = 1; | ||
1266 | kfree(cm_node); | 1260 | kfree(cm_node); |
1267 | return 0; | 1261 | return 0; |
1268 | } | 1262 | } |
@@ -1999,13 +1993,17 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1999 | if (loopbackremotelistener == NULL) { | 1993 | if (loopbackremotelistener == NULL) { |
2000 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 1994 | create_event(cm_node, NES_CM_EVENT_ABORTED); |
2001 | } else { | 1995 | } else { |
2002 | atomic_inc(&cm_loopbacks); | ||
2003 | loopback_cm_info = *cm_info; | 1996 | loopback_cm_info = *cm_info; |
2004 | loopback_cm_info.loc_port = cm_info->rem_port; | 1997 | loopback_cm_info.loc_port = cm_info->rem_port; |
2005 | loopback_cm_info.rem_port = cm_info->loc_port; | 1998 | loopback_cm_info.rem_port = cm_info->loc_port; |
2006 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; | 1999 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; |
2007 | loopbackremotenode = make_cm_node(cm_core, nesvnic, | 2000 | loopbackremotenode = make_cm_node(cm_core, nesvnic, |
2008 | &loopback_cm_info, loopbackremotelistener); | 2001 | &loopback_cm_info, loopbackremotelistener); |
2002 | if (!loopbackremotenode) { | ||
2003 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
2004 | return NULL; | ||
2005 | } | ||
2006 | atomic_inc(&cm_loopbacks); | ||
2009 | loopbackremotenode->loopbackpartner = cm_node; | 2007 | loopbackremotenode->loopbackpartner = cm_node; |
2010 | loopbackremotenode->tcp_cntxt.rcv_wscale = | 2008 | loopbackremotenode->tcp_cntxt.rcv_wscale = |
2011 | NES_CM_DEFAULT_RCV_WND_SCALE; | 2009 | NES_CM_DEFAULT_RCV_WND_SCALE; |
@@ -2690,6 +2688,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2690 | struct ib_mr *ibmr = NULL; | 2688 | struct ib_mr *ibmr = NULL; |
2691 | struct ib_phys_buf ibphysbuf; | 2689 | struct ib_phys_buf ibphysbuf; |
2692 | struct nes_pd *nespd; | 2690 | struct nes_pd *nespd; |
2691 | u64 tagged_offset; | ||
2693 | 2692 | ||
2694 | 2693 | ||
2695 | 2694 | ||
@@ -2755,10 +2754,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2755 | ibphysbuf.addr = nesqp->ietf_frame_pbase; | 2754 | ibphysbuf.addr = nesqp->ietf_frame_pbase; |
2756 | ibphysbuf.size = conn_param->private_data_len + | 2755 | ibphysbuf.size = conn_param->private_data_len + |
2757 | sizeof(struct ietf_mpa_frame); | 2756 | sizeof(struct ietf_mpa_frame); |
2757 | tagged_offset = (u64)(unsigned long)nesqp->ietf_frame; | ||
2758 | ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, | 2758 | ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, |
2759 | &ibphysbuf, 1, | 2759 | &ibphysbuf, 1, |
2760 | IB_ACCESS_LOCAL_WRITE, | 2760 | IB_ACCESS_LOCAL_WRITE, |
2761 | (u64 *)&nesqp->ietf_frame); | 2761 | &tagged_offset); |
2762 | if (!ibmr) { | 2762 | if (!ibmr) { |
2763 | nes_debug(NES_DBG_CM, "Unable to register memory region" | 2763 | nes_debug(NES_DBG_CM, "Unable to register memory region" |
2764 | "for lSMM for cm_node = %p \n", | 2764 | "for lSMM for cm_node = %p \n", |
@@ -2782,7 +2782,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2782 | sizeof(struct ietf_mpa_frame)); | 2782 | sizeof(struct ietf_mpa_frame)); |
2783 | set_wqe_64bit_value(wqe->wqe_words, | 2783 | set_wqe_64bit_value(wqe->wqe_words, |
2784 | NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, | 2784 | NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, |
2785 | (u64)nesqp->ietf_frame); | 2785 | (u64)(unsigned long)nesqp->ietf_frame); |
2786 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = | 2786 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = |
2787 | cpu_to_le32(conn_param->private_data_len + | 2787 | cpu_to_le32(conn_param->private_data_len + |
2788 | sizeof(struct ietf_mpa_frame)); | 2788 | sizeof(struct ietf_mpa_frame)); |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index d5f778202eb7..80bba1892571 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -298,7 +298,6 @@ struct nes_cm_node { | |||
298 | struct nes_vnic *nesvnic; | 298 | struct nes_vnic *nesvnic; |
299 | int apbvt_set; | 299 | int apbvt_set; |
300 | int accept_pend; | 300 | int accept_pend; |
301 | int freed; | ||
302 | struct list_head timer_entry; | 301 | struct list_head timer_entry; |
303 | struct list_head reset_entry; | 302 | struct list_head reset_entry; |
304 | struct nes_qp *nesqp; | 303 | struct nes_qp *nesqp; |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 52e734042b8e..d6fc9ae44062 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -46,6 +46,10 @@ static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR; | |||
46 | module_param(nes_lro_max_aggr, uint, 0444); | 46 | module_param(nes_lro_max_aggr, uint, 0444); |
47 | MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation"); | 47 | MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation"); |
48 | 48 | ||
49 | static int wide_ppm_offset; | ||
50 | module_param(wide_ppm_offset, int, 0644); | ||
51 | MODULE_PARM_DESC(wide_ppm_offset, "Increase CX4 interface clock ppm offset, 0=100ppm (default), 1=300ppm"); | ||
52 | |||
49 | static u32 crit_err_count; | 53 | static u32 crit_err_count; |
50 | u32 int_mod_timer_init; | 54 | u32 int_mod_timer_init; |
51 | u32 int_mod_cq_depth_256; | 55 | u32 int_mod_cq_depth_256; |
@@ -546,8 +550,11 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { | |||
546 | msleep(1); | 550 | msleep(1); |
547 | } | 551 | } |
548 | if (int_cnt > 1) { | 552 | if (int_cnt > 1) { |
553 | u32 sds; | ||
549 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | 554 | spin_lock_irqsave(&nesadapter->phy_lock, flags); |
550 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088); | 555 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); |
556 | sds |= 0x00000040; | ||
557 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); | ||
551 | mh_detected++; | 558 | mh_detected++; |
552 | reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); | 559 | reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); |
553 | reset_value |= 0x0000003d; | 560 | reset_value |= 0x0000003d; |
@@ -736,39 +743,49 @@ static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, | |||
736 | { | 743 | { |
737 | int i; | 744 | int i; |
738 | u32 u32temp; | 745 | u32 u32temp; |
739 | u32 serdes_common_control; | 746 | u32 sds; |
740 | 747 | ||
741 | if (hw_rev != NE020_REV) { | 748 | if (hw_rev != NE020_REV) { |
742 | /* init serdes 0 */ | 749 | /* init serdes 0 */ |
750 | if (wide_ppm_offset && (nesadapter->phy_type[0] == NES_PHY_TYPE_CX4)) | ||
751 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA); | ||
752 | else | ||
753 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); | ||
743 | 754 | ||
744 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); | ||
745 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { | 755 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { |
746 | serdes_common_control = nes_read_indexed(nesdev, | 756 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0); |
747 | NES_IDX_ETH_SERDES_COMMON_CONTROL0); | 757 | sds |= 0x00000100; |
748 | serdes_common_control |= 0x000000100; | 758 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds); |
749 | nes_write_indexed(nesdev, | ||
750 | NES_IDX_ETH_SERDES_COMMON_CONTROL0, | ||
751 | serdes_common_control); | ||
752 | } else if (!OneG_Mode) { | ||
753 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); | ||
754 | } | 759 | } |
755 | if (((port_count > 1) && | 760 | if (!OneG_Mode) |
756 | (nesadapter->phy_type[0] != NES_PHY_TYPE_PUMA_1G)) || | 761 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); |
757 | ((port_count > 2) && | 762 | |
758 | (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G))) { | 763 | if (port_count < 2) |
759 | /* init serdes 1 */ | 764 | return 0; |
760 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); | 765 | |
761 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { | 766 | /* init serdes 1 */ |
762 | serdes_common_control = nes_read_indexed(nesdev, | 767 | switch (nesadapter->phy_type[1]) { |
763 | NES_IDX_ETH_SERDES_COMMON_CONTROL1); | 768 | case NES_PHY_TYPE_ARGUS: |
764 | serdes_common_control |= 0x000000100; | 769 | case NES_PHY_TYPE_SFP_D: |
765 | nes_write_indexed(nesdev, | 770 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000); |
766 | NES_IDX_ETH_SERDES_COMMON_CONTROL1, | 771 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000); |
767 | serdes_common_control); | 772 | break; |
768 | } else if (!OneG_Mode) { | 773 | case NES_PHY_TYPE_CX4: |
769 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); | 774 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); |
770 | } | 775 | sds &= 0xFFFFFFBF; |
776 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); | ||
777 | if (wide_ppm_offset) | ||
778 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA); | ||
779 | else | ||
780 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); | ||
781 | break; | ||
782 | case NES_PHY_TYPE_PUMA_1G: | ||
783 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); | ||
784 | sds |= 0x000000100; | ||
785 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); | ||
771 | } | 786 | } |
787 | if (!OneG_Mode) | ||
788 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); | ||
772 | } else { | 789 | } else { |
773 | /* init serdes 0 */ | 790 | /* init serdes 0 */ |
774 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); | 791 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); |
@@ -1259,203 +1276,162 @@ int nes_init_phy(struct nes_device *nesdev) | |||
1259 | { | 1276 | { |
1260 | struct nes_adapter *nesadapter = nesdev->nesadapter; | 1277 | struct nes_adapter *nesadapter = nesdev->nesadapter; |
1261 | u32 counter = 0; | 1278 | u32 counter = 0; |
1262 | u32 sds_common_control0; | 1279 | u32 sds; |
1263 | u32 mac_index = nesdev->mac_index; | 1280 | u32 mac_index = nesdev->mac_index; |
1264 | u32 tx_config = 0; | 1281 | u32 tx_config = 0; |
1265 | u16 phy_data; | 1282 | u16 phy_data; |
1266 | u32 temp_phy_data = 0; | 1283 | u32 temp_phy_data = 0; |
1267 | u32 temp_phy_data2 = 0; | 1284 | u32 temp_phy_data2 = 0; |
1268 | u32 i = 0; | 1285 | u8 phy_type = nesadapter->phy_type[mac_index]; |
1286 | u8 phy_index = nesadapter->phy_index[mac_index]; | ||
1269 | 1287 | ||
1270 | if ((nesadapter->OneG_Mode) && | 1288 | if ((nesadapter->OneG_Mode) && |
1271 | (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) { | 1289 | (phy_type != NES_PHY_TYPE_PUMA_1G)) { |
1272 | nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index); | 1290 | nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index); |
1273 | if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) { | 1291 | if (phy_type == NES_PHY_TYPE_1G) { |
1274 | printk(PFX "%s: Programming mdc config for 1G\n", __func__); | ||
1275 | tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); | 1292 | tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); |
1276 | tx_config &= 0xFFFFFFE3; | 1293 | tx_config &= 0xFFFFFFE3; |
1277 | tx_config |= 0x04; | 1294 | tx_config |= 0x04; |
1278 | nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); | 1295 | nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); |
1279 | } | 1296 | } |
1280 | 1297 | ||
1281 | nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data); | 1298 | nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data); |
1282 | nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n", | 1299 | nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000); |
1283 | nesadapter->phy_index[mac_index], phy_data); | ||
1284 | nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000); | ||
1285 | 1300 | ||
1286 | /* Reset the PHY */ | 1301 | /* Reset the PHY */ |
1287 | nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], 0x8000); | 1302 | nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000); |
1288 | udelay(100); | 1303 | udelay(100); |
1289 | counter = 0; | 1304 | counter = 0; |
1290 | do { | 1305 | do { |
1291 | nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); | 1306 | nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data); |
1292 | nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data); | 1307 | if (counter++ > 100) |
1293 | if (counter++ > 100) break; | 1308 | break; |
1294 | } while (phy_data & 0x8000); | 1309 | } while (phy_data & 0x8000); |
1295 | 1310 | ||
1296 | /* Setting no phy loopback */ | 1311 | /* Setting no phy loopback */ |
1297 | phy_data &= 0xbfff; | 1312 | phy_data &= 0xbfff; |
1298 | phy_data |= 0x1140; | 1313 | phy_data |= 0x1140; |
1299 | nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data); | 1314 | nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data); |
1300 | nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); | 1315 | nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data); |
1301 | nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data); | 1316 | nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data); |
1302 | 1317 | nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data); | |
1303 | nes_read_1G_phy_reg(nesdev, 0x17, nesadapter->phy_index[mac_index], &phy_data); | ||
1304 | nes_debug(NES_DBG_PHY, "Phy data from register 0x17 = 0x%X.\n", phy_data); | ||
1305 | |||
1306 | nes_read_1G_phy_reg(nesdev, 0x1e, nesadapter->phy_index[mac_index], &phy_data); | ||
1307 | nes_debug(NES_DBG_PHY, "Phy data from register 0x1e = 0x%X.\n", phy_data); | ||
1308 | 1318 | ||
1309 | /* Setting the interrupt mask */ | 1319 | /* Setting the interrupt mask */ |
1310 | nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data); | 1320 | nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data); |
1311 | nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data); | 1321 | nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee); |
1312 | nes_write_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], 0xffee); | 1322 | nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data); |
1313 | |||
1314 | nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data); | ||
1315 | nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data); | ||
1316 | 1323 | ||
1317 | /* turning on flow control */ | 1324 | /* turning on flow control */ |
1318 | nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data); | 1325 | nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data); |
1319 | nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data); | 1326 | nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00); |
1320 | nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], | 1327 | nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data); |
1321 | (phy_data & ~(0x03E0)) | 0xc00); | ||
1322 | /* nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], | ||
1323 | phy_data | 0xc00); */ | ||
1324 | nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data); | ||
1325 | nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data); | ||
1326 | |||
1327 | nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data); | ||
1328 | nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data); | ||
1329 | /* Clear Half duplex */ | ||
1330 | nes_write_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], | ||
1331 | phy_data & ~(0x0100)); | ||
1332 | nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data); | ||
1333 | nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data); | ||
1334 | |||
1335 | nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); | ||
1336 | nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data | 0x0300); | ||
1337 | } else { | ||
1338 | if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) || | ||
1339 | (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) { | ||
1340 | /* setup 10G MDIO operation */ | ||
1341 | tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); | ||
1342 | tx_config &= 0xFFFFFFE3; | ||
1343 | tx_config |= 0x15; | ||
1344 | nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); | ||
1345 | } | ||
1346 | if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) { | ||
1347 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee); | ||
1348 | 1328 | ||
1349 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1329 | /* Clear Half duplex */ |
1350 | mdelay(10); | 1330 | nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data); |
1351 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee); | 1331 | nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100)); |
1352 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1332 | nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data); |
1353 | 1333 | ||
1354 | /* | 1334 | nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data); |
1355 | * if firmware is already running (like from a | 1335 | nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300); |
1356 | * driver un-load/load, don't do anything. | ||
1357 | */ | ||
1358 | if (temp_phy_data == temp_phy_data2) { | ||
1359 | /* configure QT2505 AMCC PHY */ | ||
1360 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0x0000, 0x8000); | ||
1361 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0000); | ||
1362 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc302, 0x0044); | ||
1363 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc318, 0x0052); | ||
1364 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008); | ||
1365 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098); | ||
1366 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00); | ||
1367 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0001); | ||
1368 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528); | ||
1369 | 1336 | ||
1370 | /* | 1337 | return 0; |
1371 | * remove micro from reset; chip boots from ROM, | 1338 | } |
1372 | * uploads EEPROM f/w image, uC executes f/w | ||
1373 | */ | ||
1374 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0002); | ||
1375 | 1339 | ||
1376 | /* | 1340 | if ((phy_type == NES_PHY_TYPE_IRIS) || |
1377 | * wait for heart beat to start to | 1341 | (phy_type == NES_PHY_TYPE_ARGUS) || |
1378 | * know loading is done | 1342 | (phy_type == NES_PHY_TYPE_SFP_D)) { |
1379 | */ | 1343 | /* setup 10G MDIO operation */ |
1380 | counter = 0; | 1344 | tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); |
1381 | do { | 1345 | tx_config &= 0xFFFFFFE3; |
1382 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee); | 1346 | tx_config |= 0x15; |
1383 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1347 | nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); |
1384 | if (counter++ > 1000) { | 1348 | } |
1385 | nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from heartbeat check <this is bad!!!> \n"); | 1349 | if ((phy_type == NES_PHY_TYPE_ARGUS) || |
1386 | break; | 1350 | (phy_type == NES_PHY_TYPE_SFP_D)) { |
1387 | } | 1351 | /* Check firmware heartbeat */ |
1388 | mdelay(100); | 1352 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); |
1389 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee); | 1353 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1390 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1354 | udelay(1500); |
1391 | } while ((temp_phy_data2 == temp_phy_data)); | 1355 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); |
1356 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1357 | |||
1358 | if (temp_phy_data != temp_phy_data2) | ||
1359 | return 0; | ||
1392 | 1360 | ||
1393 | /* | 1361 | /* no heartbeat, configure the PHY */ |
1394 | * wait for tracking to start to know | 1362 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000); |
1395 | * f/w is good to go | 1363 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000); |
1396 | */ | 1364 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A); |
1397 | counter = 0; | 1365 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052); |
1398 | do { | 1366 | if (phy_type == NES_PHY_TYPE_ARGUS) { |
1399 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7fd); | 1367 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C); |
1400 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1368 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008); |
1401 | if (counter++ > 1000) { | 1369 | } else { |
1402 | nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from status check <this is bad!!!> \n"); | 1370 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004); |
1403 | break; | 1371 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038); |
1404 | } | 1372 | } |
1405 | mdelay(1000); | 1373 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098); |
1406 | /* | 1374 | nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00); |
1407 | * nes_debug(NES_DBG_PHY, "AMCC PHY- phy_status not ready yet = 0x%02X\n", | 1375 | nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001); |
1408 | * temp_phy_data); | ||
1409 | */ | ||
1410 | } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70)); | ||
1411 | |||
1412 | /* set LOS Control invert RXLOSB_I_PADINV */ | ||
1413 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd003, 0x0000); | ||
1414 | /* set LOS Control to mask of RXLOSB_I */ | ||
1415 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc314, 0x0042); | ||
1416 | /* set LED1 to input mode (LED1 and LED2 share same LED) */ | ||
1417 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd006, 0x0007); | ||
1418 | /* set LED2 to RX link_status and activity */ | ||
1419 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd007, 0x000A); | ||
1420 | /* set LED3 to RX link_status */ | ||
1421 | nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd008, 0x0009); | ||
1422 | 1376 | ||
1423 | /* | 1377 | /* setup LEDs */ |
1424 | * reset the res-calibration on t2 | 1378 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007); |
1425 | * serdes; ensures it is stable after | 1379 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A); |
1426 | * the amcc phy is stable | 1380 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009); |
1427 | */ | ||
1428 | 1381 | ||
1429 | sds_common_control0 = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0); | 1382 | nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528); |
1430 | sds_common_control0 |= 0x1; | ||
1431 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0); | ||
1432 | 1383 | ||
1433 | /* release the res-calibration reset */ | 1384 | /* Bring PHY out of reset */ |
1434 | sds_common_control0 &= 0xfffffffe; | 1385 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002); |
1435 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0); | ||
1436 | 1386 | ||
1437 | i = 0; | 1387 | /* Check for heartbeat */ |
1438 | while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040) | 1388 | counter = 0; |
1439 | && (i++ < 5000)) { | 1389 | mdelay(690); |
1440 | /* mdelay(1); */ | 1390 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); |
1441 | } | 1391 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1392 | do { | ||
1393 | if (counter++ > 150) { | ||
1394 | nes_debug(NES_DBG_PHY, "No PHY heartbeat\n"); | ||
1395 | break; | ||
1396 | } | ||
1397 | mdelay(1); | ||
1398 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); | ||
1399 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1400 | } while ((temp_phy_data2 == temp_phy_data)); | ||
1442 | 1401 | ||
1443 | /* | 1402 | /* wait for tracking */ |
1444 | * wait for link train done before moving on, | 1403 | counter = 0; |
1445 | * or will get an interupt storm | 1404 | do { |
1446 | */ | 1405 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd); |
1447 | counter = 0; | 1406 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1448 | do { | 1407 | if (counter++ > 300) { |
1449 | temp_phy_data = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1408 | nes_debug(NES_DBG_PHY, "PHY did not track\n"); |
1450 | (0x200 * (nesdev->mac_index & 1))); | 1409 | break; |
1451 | if (counter++ > 1000) { | ||
1452 | nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from link train wait <this is bad, link didnt train!!!>\n"); | ||
1453 | break; | ||
1454 | } | ||
1455 | mdelay(1); | ||
1456 | } while (((temp_phy_data & 0x0f1f0000) != 0x0f0f0000)); | ||
1457 | } | 1410 | } |
1458 | } | 1411 | mdelay(10); |
1412 | } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70)); | ||
1413 | |||
1414 | /* setup signal integrity */ | ||
1415 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000); | ||
1416 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE); | ||
1417 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032); | ||
1418 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002); | ||
1419 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063); | ||
1420 | |||
1421 | /* reset serdes */ | ||
1422 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + | ||
1423 | mac_index * 0x200); | ||
1424 | sds |= 0x1; | ||
1425 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + | ||
1426 | mac_index * 0x200, sds); | ||
1427 | sds &= 0xfffffffe; | ||
1428 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + | ||
1429 | mac_index * 0x200, sds); | ||
1430 | |||
1431 | counter = 0; | ||
1432 | while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040) | ||
1433 | && (counter++ < 5000)) | ||
1434 | ; | ||
1459 | } | 1435 | } |
1460 | return 0; | 1436 | return 0; |
1461 | } | 1437 | } |
@@ -2359,6 +2335,7 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2359 | u16 temp_phy_data; | 2335 | u16 temp_phy_data; |
2360 | u32 pcs_val = 0x0f0f0000; | 2336 | u32 pcs_val = 0x0f0f0000; |
2361 | u32 pcs_mask = 0x0f1f0000; | 2337 | u32 pcs_mask = 0x0f1f0000; |
2338 | u32 cdr_ctrl; | ||
2362 | 2339 | ||
2363 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | 2340 | spin_lock_irqsave(&nesadapter->phy_lock, flags); |
2364 | if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) { | 2341 | if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) { |
@@ -2473,6 +2450,7 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2473 | break; | 2450 | break; |
2474 | 2451 | ||
2475 | case NES_PHY_TYPE_ARGUS: | 2452 | case NES_PHY_TYPE_ARGUS: |
2453 | case NES_PHY_TYPE_SFP_D: | ||
2476 | /* clear the alarms */ | 2454 | /* clear the alarms */ |
2477 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008); | 2455 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008); |
2478 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001); | 2456 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001); |
@@ -2483,19 +2461,18 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2483 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004); | 2461 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004); |
2484 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005); | 2462 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005); |
2485 | /* check link status */ | 2463 | /* check link status */ |
2486 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1); | 2464 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003); |
2487 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 2465 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
2488 | u32temp = 100; | ||
2489 | do { | ||
2490 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1); | ||
2491 | 2466 | ||
2492 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 2467 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); |
2493 | if ((phy_data == temp_phy_data) || (!(--u32temp))) | 2468 | nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
2494 | break; | 2469 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); |
2495 | temp_phy_data = phy_data; | 2470 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
2496 | } while (1); | 2471 | |
2472 | phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0; | ||
2473 | |||
2497 | nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n", | 2474 | nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n", |
2498 | __func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP"); | 2475 | __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP"); |
2499 | break; | 2476 | break; |
2500 | 2477 | ||
2501 | case NES_PHY_TYPE_PUMA_1G: | 2478 | case NES_PHY_TYPE_PUMA_1G: |
@@ -2511,6 +2488,17 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2511 | } | 2488 | } |
2512 | 2489 | ||
2513 | if (phy_data & 0x0004) { | 2490 | if (phy_data & 0x0004) { |
2491 | if (wide_ppm_offset && | ||
2492 | (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) && | ||
2493 | (nesadapter->hw_rev != NE020_REV)) { | ||
2494 | cdr_ctrl = nes_read_indexed(nesdev, | ||
2495 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2496 | mac_index * 0x200); | ||
2497 | nes_write_indexed(nesdev, | ||
2498 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2499 | mac_index * 0x200, | ||
2500 | cdr_ctrl | 0x000F0000); | ||
2501 | } | ||
2514 | nesadapter->mac_link_down[mac_index] = 0; | 2502 | nesadapter->mac_link_down[mac_index] = 0; |
2515 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | 2503 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { |
2516 | nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n", | 2504 | nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n", |
@@ -2525,6 +2513,17 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2525 | } | 2513 | } |
2526 | } | 2514 | } |
2527 | } else { | 2515 | } else { |
2516 | if (wide_ppm_offset && | ||
2517 | (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) && | ||
2518 | (nesadapter->hw_rev != NE020_REV)) { | ||
2519 | cdr_ctrl = nes_read_indexed(nesdev, | ||
2520 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2521 | mac_index * 0x200); | ||
2522 | nes_write_indexed(nesdev, | ||
2523 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2524 | mac_index * 0x200, | ||
2525 | cdr_ctrl & 0xFFF0FFFF); | ||
2526 | } | ||
2528 | nesadapter->mac_link_down[mac_index] = 1; | 2527 | nesadapter->mac_link_down[mac_index] = 1; |
2529 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | 2528 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { |
2530 | nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n", | 2529 | nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n", |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index f41a8710d2a8..c3654c6383fe 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
@@ -35,12 +35,14 @@ | |||
35 | 35 | ||
36 | #include <linux/inet_lro.h> | 36 | #include <linux/inet_lro.h> |
37 | 37 | ||
38 | #define NES_PHY_TYPE_CX4 1 | ||
38 | #define NES_PHY_TYPE_1G 2 | 39 | #define NES_PHY_TYPE_1G 2 |
39 | #define NES_PHY_TYPE_IRIS 3 | 40 | #define NES_PHY_TYPE_IRIS 3 |
40 | #define NES_PHY_TYPE_ARGUS 4 | 41 | #define NES_PHY_TYPE_ARGUS 4 |
41 | #define NES_PHY_TYPE_PUMA_1G 5 | 42 | #define NES_PHY_TYPE_PUMA_1G 5 |
42 | #define NES_PHY_TYPE_PUMA_10G 6 | 43 | #define NES_PHY_TYPE_PUMA_10G 6 |
43 | #define NES_PHY_TYPE_GLADIUS 7 | 44 | #define NES_PHY_TYPE_GLADIUS 7 |
45 | #define NES_PHY_TYPE_SFP_D 8 | ||
44 | 46 | ||
45 | #define NES_MULTICAST_PF_MAX 8 | 47 | #define NES_MULTICAST_PF_MAX 8 |
46 | 48 | ||
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index ecb1f6fd6276..c6e6611d3016 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c | |||
@@ -1426,49 +1426,55 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd | |||
1426 | struct nes_vnic *nesvnic = netdev_priv(netdev); | 1426 | struct nes_vnic *nesvnic = netdev_priv(netdev); |
1427 | struct nes_device *nesdev = nesvnic->nesdev; | 1427 | struct nes_device *nesdev = nesvnic->nesdev; |
1428 | struct nes_adapter *nesadapter = nesdev->nesadapter; | 1428 | struct nes_adapter *nesadapter = nesdev->nesadapter; |
1429 | u32 mac_index = nesdev->mac_index; | ||
1430 | u8 phy_type = nesadapter->phy_type[mac_index]; | ||
1431 | u8 phy_index = nesadapter->phy_index[mac_index]; | ||
1429 | u16 phy_data; | 1432 | u16 phy_data; |
1430 | 1433 | ||
1431 | et_cmd->duplex = DUPLEX_FULL; | 1434 | et_cmd->duplex = DUPLEX_FULL; |
1432 | et_cmd->port = PORT_MII; | 1435 | et_cmd->port = PORT_MII; |
1436 | et_cmd->maxtxpkt = 511; | ||
1437 | et_cmd->maxrxpkt = 511; | ||
1433 | 1438 | ||
1434 | if (nesadapter->OneG_Mode) { | 1439 | if (nesadapter->OneG_Mode) { |
1435 | et_cmd->speed = SPEED_1000; | 1440 | et_cmd->speed = SPEED_1000; |
1436 | if (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) { | 1441 | if (phy_type == NES_PHY_TYPE_PUMA_1G) { |
1437 | et_cmd->supported = SUPPORTED_1000baseT_Full; | 1442 | et_cmd->supported = SUPPORTED_1000baseT_Full; |
1438 | et_cmd->advertising = ADVERTISED_1000baseT_Full; | 1443 | et_cmd->advertising = ADVERTISED_1000baseT_Full; |
1439 | et_cmd->autoneg = AUTONEG_DISABLE; | 1444 | et_cmd->autoneg = AUTONEG_DISABLE; |
1440 | et_cmd->transceiver = XCVR_INTERNAL; | 1445 | et_cmd->transceiver = XCVR_INTERNAL; |
1441 | et_cmd->phy_address = nesdev->mac_index; | 1446 | et_cmd->phy_address = mac_index; |
1442 | } else { | 1447 | } else { |
1443 | et_cmd->supported = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg; | 1448 | et_cmd->supported = SUPPORTED_1000baseT_Full |
1444 | et_cmd->advertising = ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg; | 1449 | | SUPPORTED_Autoneg; |
1445 | nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index], &phy_data); | 1450 | et_cmd->advertising = ADVERTISED_1000baseT_Full |
1451 | | ADVERTISED_Autoneg; | ||
1452 | nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data); | ||
1446 | if (phy_data & 0x1000) | 1453 | if (phy_data & 0x1000) |
1447 | et_cmd->autoneg = AUTONEG_ENABLE; | 1454 | et_cmd->autoneg = AUTONEG_ENABLE; |
1448 | else | 1455 | else |
1449 | et_cmd->autoneg = AUTONEG_DISABLE; | 1456 | et_cmd->autoneg = AUTONEG_DISABLE; |
1450 | et_cmd->transceiver = XCVR_EXTERNAL; | 1457 | et_cmd->transceiver = XCVR_EXTERNAL; |
1451 | et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index]; | 1458 | et_cmd->phy_address = phy_index; |
1452 | } | 1459 | } |
1460 | return 0; | ||
1461 | } | ||
1462 | if ((phy_type == NES_PHY_TYPE_IRIS) || | ||
1463 | (phy_type == NES_PHY_TYPE_ARGUS) || | ||
1464 | (phy_type == NES_PHY_TYPE_SFP_D)) { | ||
1465 | et_cmd->transceiver = XCVR_EXTERNAL; | ||
1466 | et_cmd->port = PORT_FIBRE; | ||
1467 | et_cmd->supported = SUPPORTED_FIBRE; | ||
1468 | et_cmd->advertising = ADVERTISED_FIBRE; | ||
1469 | et_cmd->phy_address = phy_index; | ||
1453 | } else { | 1470 | } else { |
1454 | if ((nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) || | 1471 | et_cmd->transceiver = XCVR_INTERNAL; |
1455 | (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_ARGUS)) { | 1472 | et_cmd->supported = SUPPORTED_10000baseT_Full; |
1456 | et_cmd->transceiver = XCVR_EXTERNAL; | 1473 | et_cmd->advertising = ADVERTISED_10000baseT_Full; |
1457 | et_cmd->port = PORT_FIBRE; | 1474 | et_cmd->phy_address = mac_index; |
1458 | et_cmd->supported = SUPPORTED_FIBRE; | ||
1459 | et_cmd->advertising = ADVERTISED_FIBRE; | ||
1460 | et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index]; | ||
1461 | } else { | ||
1462 | et_cmd->transceiver = XCVR_INTERNAL; | ||
1463 | et_cmd->supported = SUPPORTED_10000baseT_Full; | ||
1464 | et_cmd->advertising = ADVERTISED_10000baseT_Full; | ||
1465 | et_cmd->phy_address = nesdev->mac_index; | ||
1466 | } | ||
1467 | et_cmd->speed = SPEED_10000; | ||
1468 | et_cmd->autoneg = AUTONEG_DISABLE; | ||
1469 | } | 1475 | } |
1470 | et_cmd->maxtxpkt = 511; | 1476 | et_cmd->speed = SPEED_10000; |
1471 | et_cmd->maxrxpkt = 511; | 1477 | et_cmd->autoneg = AUTONEG_DISABLE; |
1472 | return 0; | 1478 | return 0; |
1473 | } | 1479 | } |
1474 | 1480 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 5a76a5510350..4c57f329dd50 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -70,12 +70,14 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
70 | */ | 70 | */ |
71 | if (ppriv->pkey == pkey) { | 71 | if (ppriv->pkey == pkey) { |
72 | result = -ENOTUNIQ; | 72 | result = -ENOTUNIQ; |
73 | priv = NULL; | ||
73 | goto err; | 74 | goto err; |
74 | } | 75 | } |
75 | 76 | ||
76 | list_for_each_entry(priv, &ppriv->child_intfs, list) { | 77 | list_for_each_entry(priv, &ppriv->child_intfs, list) { |
77 | if (priv->pkey == pkey) { | 78 | if (priv->pkey == pkey) { |
78 | result = -ENOTUNIQ; | 79 | result = -ENOTUNIQ; |
80 | priv = NULL; | ||
79 | goto err; | 81 | goto err; |
80 | } | 82 | } |
81 | } | 83 | } |
@@ -96,7 +98,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
96 | 98 | ||
97 | result = ipoib_set_dev_features(priv, ppriv->ca); | 99 | result = ipoib_set_dev_features(priv, ppriv->ca); |
98 | if (result) | 100 | if (result) |
99 | goto device_init_failed; | 101 | goto err; |
100 | 102 | ||
101 | priv->pkey = pkey; | 103 | priv->pkey = pkey; |
102 | 104 | ||
@@ -109,7 +111,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
109 | ipoib_warn(ppriv, "failed to initialize subinterface: " | 111 | ipoib_warn(ppriv, "failed to initialize subinterface: " |
110 | "device %s, port %d", | 112 | "device %s, port %d", |
111 | ppriv->ca->name, ppriv->port); | 113 | ppriv->ca->name, ppriv->port); |
112 | goto device_init_failed; | 114 | goto err; |
113 | } | 115 | } |
114 | 116 | ||
115 | result = register_netdevice(priv->dev); | 117 | result = register_netdevice(priv->dev); |
@@ -146,19 +148,19 @@ sysfs_failed: | |||
146 | register_failed: | 148 | register_failed: |
147 | ipoib_dev_cleanup(priv->dev); | 149 | ipoib_dev_cleanup(priv->dev); |
148 | 150 | ||
149 | device_init_failed: | ||
150 | free_netdev(priv->dev); | ||
151 | |||
152 | err: | 151 | err: |
153 | mutex_unlock(&ppriv->vlan_mutex); | 152 | mutex_unlock(&ppriv->vlan_mutex); |
154 | rtnl_unlock(); | 153 | rtnl_unlock(); |
154 | if (priv) | ||
155 | free_netdev(priv->dev); | ||
156 | |||
155 | return result; | 157 | return result; |
156 | } | 158 | } |
157 | 159 | ||
158 | int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | 160 | int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) |
159 | { | 161 | { |
160 | struct ipoib_dev_priv *ppriv, *priv, *tpriv; | 162 | struct ipoib_dev_priv *ppriv, *priv, *tpriv; |
161 | int ret = -ENOENT; | 163 | struct net_device *dev = NULL; |
162 | 164 | ||
163 | if (!capable(CAP_NET_ADMIN)) | 165 | if (!capable(CAP_NET_ADMIN)) |
164 | return -EPERM; | 166 | return -EPERM; |
@@ -172,14 +174,17 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
172 | unregister_netdevice(priv->dev); | 174 | unregister_netdevice(priv->dev); |
173 | ipoib_dev_cleanup(priv->dev); | 175 | ipoib_dev_cleanup(priv->dev); |
174 | list_del(&priv->list); | 176 | list_del(&priv->list); |
175 | free_netdev(priv->dev); | 177 | dev = priv->dev; |
176 | |||
177 | ret = 0; | ||
178 | break; | 178 | break; |
179 | } | 179 | } |
180 | } | 180 | } |
181 | mutex_unlock(&ppriv->vlan_mutex); | 181 | mutex_unlock(&ppriv->vlan_mutex); |
182 | rtnl_unlock(); | 182 | rtnl_unlock(); |
183 | 183 | ||
184 | return ret; | 184 | if (dev) { |
185 | free_netdev(dev); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | return -ENODEV; | ||
185 | } | 190 | } |
diff --git a/drivers/input/input.c b/drivers/input/input.c index ec3db3ade118..d44065d2e662 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -132,6 +132,11 @@ static void input_start_autorepeat(struct input_dev *dev, int code) | |||
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | static void input_stop_autorepeat(struct input_dev *dev) | ||
136 | { | ||
137 | del_timer(&dev->timer); | ||
138 | } | ||
139 | |||
135 | #define INPUT_IGNORE_EVENT 0 | 140 | #define INPUT_IGNORE_EVENT 0 |
136 | #define INPUT_PASS_TO_HANDLERS 1 | 141 | #define INPUT_PASS_TO_HANDLERS 1 |
137 | #define INPUT_PASS_TO_DEVICE 2 | 142 | #define INPUT_PASS_TO_DEVICE 2 |
@@ -167,6 +172,8 @@ static void input_handle_event(struct input_dev *dev, | |||
167 | __change_bit(code, dev->key); | 172 | __change_bit(code, dev->key); |
168 | if (value) | 173 | if (value) |
169 | input_start_autorepeat(dev, code); | 174 | input_start_autorepeat(dev, code); |
175 | else | ||
176 | input_stop_autorepeat(dev); | ||
170 | } | 177 | } |
171 | 178 | ||
172 | disposition = INPUT_PASS_TO_HANDLERS; | 179 | disposition = INPUT_PASS_TO_HANDLERS; |
@@ -737,11 +744,11 @@ static inline void input_wakeup_procfs_readers(void) | |||
737 | 744 | ||
738 | static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) | 745 | static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) |
739 | { | 746 | { |
740 | int state = input_devices_state; | ||
741 | |||
742 | poll_wait(file, &input_devices_poll_wait, wait); | 747 | poll_wait(file, &input_devices_poll_wait, wait); |
743 | if (state != input_devices_state) | 748 | if (file->f_version != input_devices_state) { |
749 | file->f_version = input_devices_state; | ||
744 | return POLLIN | POLLRDNORM; | 750 | return POLLIN | POLLRDNORM; |
751 | } | ||
745 | 752 | ||
746 | return 0; | 753 | return 0; |
747 | } | 754 | } |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 45470f18d7e9..f999dc60c3b8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -229,7 +229,8 @@ struct atkbd { | |||
229 | /* | 229 | /* |
230 | * System-specific ketymap fixup routine | 230 | * System-specific ketymap fixup routine |
231 | */ | 231 | */ |
232 | static void (*atkbd_platform_fixup)(struct atkbd *); | 232 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); |
233 | static void *atkbd_platform_fixup_data; | ||
233 | 234 | ||
234 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | 235 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, |
235 | ssize_t (*handler)(struct atkbd *, char *)); | 236 | ssize_t (*handler)(struct atkbd *, char *)); |
@@ -834,87 +835,64 @@ static void atkbd_disconnect(struct serio *serio) | |||
834 | } | 835 | } |
835 | 836 | ||
836 | /* | 837 | /* |
837 | * Most special keys (Fn+F?) on Dell laptops do not generate release | 838 | * generate release events for the keycodes given in data |
838 | * events so we have to do it ourselves. | ||
839 | */ | 839 | */ |
840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_apply_forced_release_keylist(struct atkbd* atkbd, |
841 | const void *data) | ||
841 | { | 842 | { |
842 | static const unsigned int forced_release_keys[] = { | 843 | const unsigned int *keys = data; |
843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 844 | unsigned int i; |
844 | }; | ||
845 | int i; | ||
846 | 845 | ||
847 | if (atkbd->set == 2) | 846 | if (atkbd->set == 2) |
848 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | 847 | for (i = 0; keys[i] != -1U; i++) |
849 | __set_bit(forced_release_keys[i], | 848 | __set_bit(keys[i], atkbd->force_release_mask); |
850 | atkbd->force_release_mask); | ||
851 | } | 849 | } |
852 | 850 | ||
853 | /* | 851 | /* |
852 | * Most special keys (Fn+F?) on Dell laptops do not generate release | ||
853 | * events so we have to do it ourselves. | ||
854 | */ | ||
855 | static unsigned int atkbd_dell_laptop_forced_release_keys[] = { | ||
856 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, -1U | ||
857 | }; | ||
858 | |||
859 | /* | ||
854 | * Perform fixup for HP system that doesn't generate release | 860 | * Perform fixup for HP system that doesn't generate release |
855 | * for its video switch | 861 | * for its video switch |
856 | */ | 862 | */ |
857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) | 863 | static unsigned int atkbd_hp_forced_release_keys[] = { |
858 | { | 864 | 0x94, -1U |
859 | static const unsigned int forced_release_keys[] = { | 865 | }; |
860 | 0x94, | ||
861 | }; | ||
862 | int i; | ||
863 | |||
864 | if (atkbd->set == 2) | ||
865 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
866 | __set_bit(forced_release_keys[i], | ||
867 | atkbd->force_release_mask); | ||
868 | } | ||
869 | 866 | ||
870 | /* | 867 | /* |
871 | * Inventec system with broken key release on volume keys | 868 | * Inventec system with broken key release on volume keys |
872 | */ | 869 | */ |
873 | static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd) | 870 | static unsigned int atkbd_inventec_forced_release_keys[] = { |
874 | { | 871 | 0xae, 0xb0, -1U |
875 | const unsigned int forced_release_keys[] = { | 872 | }; |
876 | 0xae, 0xb0, | ||
877 | }; | ||
878 | int i; | ||
879 | |||
880 | if (atkbd->set == 2) | ||
881 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
882 | __set_bit(forced_release_keys[i], | ||
883 | atkbd->force_release_mask); | ||
884 | } | ||
885 | 873 | ||
886 | /* | 874 | /* |
887 | * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release | 875 | * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release |
888 | * for its volume buttons | 876 | * for its volume buttons |
889 | */ | 877 | */ |
890 | static void atkbd_hp_zv6100_keymap_fixup(struct atkbd *atkbd) | 878 | static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { |
891 | { | 879 | 0xae, 0xb0, -1U |
892 | const unsigned int forced_release_keys[] = { | 880 | }; |
893 | 0xae, 0xb0, | ||
894 | }; | ||
895 | int i; | ||
896 | |||
897 | if (atkbd->set == 2) | ||
898 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
899 | __set_bit(forced_release_keys[i], | ||
900 | atkbd->force_release_mask); | ||
901 | } | ||
902 | 881 | ||
903 | /* | 882 | /* |
904 | * Samsung NC10 with Fn+F? key release not working | 883 | * Samsung NC10 with Fn+F? key release not working |
905 | */ | 884 | */ |
906 | static void atkbd_samsung_keymap_fixup(struct atkbd *atkbd) | 885 | static unsigned int atkbd_samsung_forced_release_keys[] = { |
907 | { | 886 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U |
908 | const unsigned int forced_release_keys[] = { | 887 | }; |
909 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, | ||
910 | }; | ||
911 | int i; | ||
912 | 888 | ||
913 | if (atkbd->set == 2) | 889 | /* |
914 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | 890 | * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop |
915 | __set_bit(forced_release_keys[i], | 891 | * do not generate release events so we have to do it ourselves. |
916 | atkbd->force_release_mask); | 892 | */ |
917 | } | 893 | static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { |
894 | 0xb0, 0xae, -1U | ||
895 | }; | ||
918 | 896 | ||
919 | /* | 897 | /* |
920 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 898 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
@@ -967,7 +945,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
967 | * Perform additional fixups | 945 | * Perform additional fixups |
968 | */ | 946 | */ |
969 | if (atkbd_platform_fixup) | 947 | if (atkbd_platform_fixup) |
970 | atkbd_platform_fixup(atkbd); | 948 | atkbd_platform_fixup(atkbd, atkbd_platform_fixup_data); |
971 | } | 949 | } |
972 | 950 | ||
973 | /* | 951 | /* |
@@ -1492,9 +1470,11 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) | |||
1492 | return sprintf(buf, "%lu\n", atkbd->err_count); | 1470 | return sprintf(buf, "%lu\n", atkbd->err_count); |
1493 | } | 1471 | } |
1494 | 1472 | ||
1495 | static int __init atkbd_setup_fixup(const struct dmi_system_id *id) | 1473 | static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) |
1496 | { | 1474 | { |
1497 | atkbd_platform_fixup = id->driver_data; | 1475 | atkbd_platform_fixup = atkbd_apply_forced_release_keylist; |
1476 | atkbd_platform_fixup_data = id->driver_data; | ||
1477 | |||
1498 | return 0; | 1478 | return 0; |
1499 | } | 1479 | } |
1500 | 1480 | ||
@@ -1505,8 +1485,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 1485 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
1506 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1486 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1507 | }, | 1487 | }, |
1508 | .callback = atkbd_setup_fixup, | 1488 | .callback = atkbd_setup_forced_release, |
1509 | .driver_data = atkbd_dell_laptop_keymap_fixup, | 1489 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
1510 | }, | 1490 | }, |
1511 | { | 1491 | { |
1512 | .ident = "Dell Laptop", | 1492 | .ident = "Dell Laptop", |
@@ -1514,8 +1494,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1514 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 1494 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
1515 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1495 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1516 | }, | 1496 | }, |
1517 | .callback = atkbd_setup_fixup, | 1497 | .callback = atkbd_setup_forced_release, |
1518 | .driver_data = atkbd_dell_laptop_keymap_fixup, | 1498 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
1519 | }, | 1499 | }, |
1520 | { | 1500 | { |
1521 | .ident = "HP 2133", | 1501 | .ident = "HP 2133", |
@@ -1523,8 +1503,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1523 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1503 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
1524 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), | 1504 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), |
1525 | }, | 1505 | }, |
1526 | .callback = atkbd_setup_fixup, | 1506 | .callback = atkbd_setup_forced_release, |
1527 | .driver_data = atkbd_hp_keymap_fixup, | 1507 | .driver_data = atkbd_hp_forced_release_keys, |
1528 | }, | 1508 | }, |
1529 | { | 1509 | { |
1530 | .ident = "HP Pavilion ZV6100", | 1510 | .ident = "HP Pavilion ZV6100", |
@@ -1532,8 +1512,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1532 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1512 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
1533 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), | 1513 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), |
1534 | }, | 1514 | }, |
1535 | .callback = atkbd_setup_fixup, | 1515 | .callback = atkbd_setup_forced_release, |
1536 | .driver_data = atkbd_hp_zv6100_keymap_fixup, | 1516 | .driver_data = atkbd_hp_zv6100_forced_release_keys, |
1537 | }, | 1517 | }, |
1538 | { | 1518 | { |
1539 | .ident = "Inventec Symphony", | 1519 | .ident = "Inventec Symphony", |
@@ -1541,8 +1521,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1541 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), | 1521 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), |
1542 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), | 1522 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), |
1543 | }, | 1523 | }, |
1544 | .callback = atkbd_setup_fixup, | 1524 | .callback = atkbd_setup_forced_release, |
1545 | .driver_data = atkbd_inventec_keymap_fixup, | 1525 | .driver_data = atkbd_inventec_forced_release_keys, |
1546 | }, | 1526 | }, |
1547 | { | 1527 | { |
1548 | .ident = "Samsung NC10", | 1528 | .ident = "Samsung NC10", |
@@ -1550,8 +1530,17 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1550 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | 1530 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), |
1551 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), | 1531 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), |
1552 | }, | 1532 | }, |
1553 | .callback = atkbd_setup_fixup, | 1533 | .callback = atkbd_setup_forced_release, |
1554 | .driver_data = atkbd_samsung_keymap_fixup, | 1534 | .driver_data = atkbd_samsung_forced_release_keys, |
1535 | }, | ||
1536 | { | ||
1537 | .ident = "Fujitsu Amilo PA 1510", | ||
1538 | .matches = { | ||
1539 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
1540 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), | ||
1541 | }, | ||
1542 | .callback = atkbd_setup_forced_release, | ||
1543 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, | ||
1555 | }, | 1544 | }, |
1556 | { } | 1545 | { } |
1557 | }; | 1546 | }; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index ee855c5202e8..e94b7d735aca 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -211,8 +211,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
211 | 211 | ||
212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
214 | printk(KERN_ERR DRV_NAME | 214 | printk(KERN_WARNING DRV_NAME |
215 | ": Invalid Debounce/Columdrive Time from pdata\n"); | 215 | ": Invalid Debounce/Columndrive Time in platform data\n"); |
216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
217 | } else { | 217 | } else { |
218 | bfin_write_KPAD_MSEL( | 218 | bfin_write_KPAD_MSEL( |
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index aacf71f3cd44..e9d639ec283d 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c | |||
@@ -198,45 +198,28 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | /* initialise HIL */ | 201 | /* initialize HIL */ |
202 | static int __init | 202 | static int __devinit hil_keyb_init(void) |
203 | hil_keyb_init(void) | ||
204 | { | 203 | { |
205 | unsigned char c; | 204 | unsigned char c; |
206 | unsigned int i, kbid; | 205 | unsigned int i, kbid; |
207 | wait_queue_head_t hil_wait; | 206 | wait_queue_head_t hil_wait; |
208 | int err; | 207 | int err; |
209 | 208 | ||
210 | if (hil_dev.dev) { | 209 | if (hil_dev.dev) |
211 | return -ENODEV; /* already initialized */ | 210 | return -ENODEV; /* already initialized */ |
212 | } | ||
213 | 211 | ||
212 | init_waitqueue_head(&hil_wait); | ||
214 | spin_lock_init(&hil_dev.lock); | 213 | spin_lock_init(&hil_dev.lock); |
214 | |||
215 | hil_dev.dev = input_allocate_device(); | 215 | hil_dev.dev = input_allocate_device(); |
216 | if (!hil_dev.dev) | 216 | if (!hil_dev.dev) |
217 | return -ENOMEM; | 217 | return -ENOMEM; |
218 | 218 | ||
219 | #if defined(CONFIG_HP300) | ||
220 | if (!MACH_IS_HP300) { | ||
221 | err = -ENODEV; | ||
222 | goto err1; | ||
223 | } | ||
224 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { | ||
225 | printk(KERN_ERR "HIL: hardware register was not found\n"); | ||
226 | err = -ENODEV; | ||
227 | goto err1; | ||
228 | } | ||
229 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { | ||
230 | printk(KERN_ERR "HIL: IOPORT region already used\n"); | ||
231 | err = -EIO; | ||
232 | goto err1; | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); | 219 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); |
237 | if (err) { | 220 | if (err) { |
238 | printk(KERN_ERR "HIL: Can't get IRQ\n"); | 221 | printk(KERN_ERR "HIL: Can't get IRQ\n"); |
239 | goto err2; | 222 | goto err1; |
240 | } | 223 | } |
241 | 224 | ||
242 | /* Turn on interrupts */ | 225 | /* Turn on interrupts */ |
@@ -246,11 +229,9 @@ hil_keyb_init(void) | |||
246 | hil_dev.valid = 0; /* clear any pending data */ | 229 | hil_dev.valid = 0; /* clear any pending data */ |
247 | hil_do(HIL_READKBDSADR, NULL, 0); | 230 | hil_do(HIL_READKBDSADR, NULL, 0); |
248 | 231 | ||
249 | init_waitqueue_head(&hil_wait); | 232 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3 * HZ); |
250 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); | 233 | if (!hil_dev.valid) |
251 | if (!hil_dev.valid) { | ||
252 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); | 234 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); |
253 | } | ||
254 | 235 | ||
255 | c = hil_dev.c; | 236 | c = hil_dev.c; |
256 | hil_dev.valid = 0; | 237 | hil_dev.valid = 0; |
@@ -268,7 +249,7 @@ hil_keyb_init(void) | |||
268 | 249 | ||
269 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) | 250 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) |
270 | if (hphilkeyb_keycode[i] != KEY_RESERVED) | 251 | if (hphilkeyb_keycode[i] != KEY_RESERVED) |
271 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); | 252 | __set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); |
272 | 253 | ||
273 | hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 254 | hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
274 | hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 255 | hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | |
@@ -287,34 +268,45 @@ hil_keyb_init(void) | |||
287 | err = input_register_device(hil_dev.dev); | 268 | err = input_register_device(hil_dev.dev); |
288 | if (err) { | 269 | if (err) { |
289 | printk(KERN_ERR "HIL: Can't register device\n"); | 270 | printk(KERN_ERR "HIL: Can't register device\n"); |
290 | goto err3; | 271 | goto err2; |
291 | } | 272 | } |
273 | |||
292 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", | 274 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", |
293 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); | 275 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); |
294 | 276 | ||
295 | return 0; | 277 | return 0; |
296 | 278 | ||
297 | err3: | 279 | err2: |
298 | hil_do(HIL_INTOFF, NULL, 0); | 280 | hil_do(HIL_INTOFF, NULL, 0); |
299 | disable_irq(HIL_IRQ); | ||
300 | free_irq(HIL_IRQ, hil_dev.dev_id); | 281 | free_irq(HIL_IRQ, hil_dev.dev_id); |
301 | err2: | ||
302 | #if defined(CONFIG_HP300) | ||
303 | release_region(HILBASE + HIL_DATA, 2); | ||
304 | err1: | 282 | err1: |
305 | #endif | ||
306 | input_free_device(hil_dev.dev); | 283 | input_free_device(hil_dev.dev); |
307 | hil_dev.dev = NULL; | 284 | hil_dev.dev = NULL; |
308 | return err; | 285 | return err; |
309 | } | 286 | } |
310 | 287 | ||
288 | static void __devexit hil_keyb_exit(void) | ||
289 | { | ||
290 | if (HIL_IRQ) | ||
291 | free_irq(HIL_IRQ, hil_dev.dev_id); | ||
292 | |||
293 | /* Turn off interrupts */ | ||
294 | hil_do(HIL_INTOFF, NULL, 0); | ||
295 | |||
296 | input_unregister_device(hil_dev.dev); | ||
297 | hil_dev.dev = NULL; | ||
298 | } | ||
311 | 299 | ||
312 | #if defined(CONFIG_PARISC) | 300 | #if defined(CONFIG_PARISC) |
313 | static int __init | 301 | static int __devinit hil_probe_chip(struct parisc_device *dev) |
314 | hil_init_chip(struct parisc_device *dev) | ||
315 | { | 302 | { |
303 | /* Only allow one HIL keyboard */ | ||
304 | if (hil_dev.dev) | ||
305 | return -ENODEV; | ||
306 | |||
316 | if (!dev->irq) { | 307 | if (!dev->irq) { |
317 | printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start); | 308 | printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%p\n", |
309 | (void *)dev->hpa.start); | ||
318 | return -ENODEV; | 310 | return -ENODEV; |
319 | } | 311 | } |
320 | 312 | ||
@@ -327,51 +319,79 @@ hil_init_chip(struct parisc_device *dev) | |||
327 | return hil_keyb_init(); | 319 | return hil_keyb_init(); |
328 | } | 320 | } |
329 | 321 | ||
322 | static int __devexit hil_remove_chip(struct parisc_device *dev) | ||
323 | { | ||
324 | hil_keyb_exit(); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
330 | static struct parisc_device_id hil_tbl[] = { | 329 | static struct parisc_device_id hil_tbl[] = { |
331 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, | 330 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, |
332 | { 0, } | 331 | { 0, } |
333 | }; | 332 | }; |
334 | 333 | ||
334 | #if 0 | ||
335 | /* Disabled to avoid conflicts with the HP SDC HIL drivers */ | ||
335 | MODULE_DEVICE_TABLE(parisc, hil_tbl); | 336 | MODULE_DEVICE_TABLE(parisc, hil_tbl); |
337 | #endif | ||
336 | 338 | ||
337 | static struct parisc_driver hil_driver = { | 339 | static struct parisc_driver hil_driver = { |
338 | .name = "hil", | 340 | .name = "hil", |
339 | .id_table = hil_tbl, | 341 | .id_table = hil_tbl, |
340 | .probe = hil_init_chip, | 342 | .probe = hil_probe_chip, |
343 | .remove = __devexit_p(hil_remove_chip), | ||
341 | }; | 344 | }; |
342 | #endif /* CONFIG_PARISC */ | ||
343 | |||
344 | 345 | ||
345 | static int __init hil_init(void) | 346 | static int __init hil_init(void) |
346 | { | 347 | { |
347 | #if defined(CONFIG_PARISC) | ||
348 | return register_parisc_driver(&hil_driver); | 348 | return register_parisc_driver(&hil_driver); |
349 | #else | ||
350 | return hil_keyb_init(); | ||
351 | #endif | ||
352 | } | 349 | } |
353 | 350 | ||
354 | |||
355 | static void __exit hil_exit(void) | 351 | static void __exit hil_exit(void) |
356 | { | 352 | { |
357 | if (HIL_IRQ) { | 353 | unregister_parisc_driver(&hil_driver); |
358 | disable_irq(HIL_IRQ); | 354 | } |
359 | free_irq(HIL_IRQ, hil_dev.dev_id); | 355 | |
356 | #else /* !CONFIG_PARISC */ | ||
357 | |||
358 | static int __init hil_init(void) | ||
359 | { | ||
360 | int error; | ||
361 | |||
362 | /* Only allow one HIL keyboard */ | ||
363 | if (hil_dev.dev) | ||
364 | return -EBUSY; | ||
365 | |||
366 | if (!MACH_IS_HP300) | ||
367 | return -ENODEV; | ||
368 | |||
369 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { | ||
370 | printk(KERN_ERR "HIL: hardware register was not found\n"); | ||
371 | return -ENODEV; | ||
360 | } | 372 | } |
361 | 373 | ||
362 | /* Turn off interrupts */ | 374 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { |
363 | hil_do(HIL_INTOFF, NULL, 0); | 375 | printk(KERN_ERR "HIL: IOPORT region already used\n"); |
376 | return -EIO; | ||
377 | } | ||
364 | 378 | ||
365 | input_unregister_device(hil_dev.dev); | 379 | error = hil_keyb_init(); |
380 | if (error) { | ||
381 | release_region(HILBASE + HIL_DATA, 2); | ||
382 | return error; | ||
383 | } | ||
366 | 384 | ||
367 | hil_dev.dev = NULL; | 385 | return 0; |
386 | } | ||
368 | 387 | ||
369 | #if defined(CONFIG_PARISC) | 388 | static void __exit hil_exit(void) |
370 | unregister_parisc_driver(&hil_driver); | 389 | { |
371 | #else | 390 | hil_keyb_exit(); |
372 | release_region(HILBASE+HIL_DATA, 2); | 391 | release_region(HILBASE + HIL_DATA, 2); |
373 | #endif | ||
374 | } | 392 | } |
375 | 393 | ||
394 | #endif /* CONFIG_PARISC */ | ||
395 | |||
376 | module_init(hil_init); | 396 | module_init(hil_init); |
377 | module_exit(hil_exit); | 397 | module_exit(hil_exit); |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 67e5553f699a..203abac1e23e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -227,4 +227,27 @@ config INPUT_PCF50633_PMU | |||
227 | Say Y to include support for delivering PMU events via input | 227 | Say Y to include support for delivering PMU events via input |
228 | layer on NXP PCF50633. | 228 | layer on NXP PCF50633. |
229 | 229 | ||
230 | config INPUT_GPIO_ROTARY_ENCODER | ||
231 | tristate "Rotary encoders connected to GPIO pins" | ||
232 | depends on GPIOLIB && GENERIC_GPIO | ||
233 | help | ||
234 | Say Y here to add support for rotary encoders connected to GPIO lines. | ||
235 | Check file:Documentation/incput/rotary_encoder.txt for more | ||
236 | information. | ||
237 | |||
238 | To compile this driver as a module, choose M here: the | ||
239 | module will be called rotary_encoder. | ||
240 | |||
241 | config INPUT_RB532_BUTTON | ||
242 | tristate "Mikrotik Routerboard 532 button interface" | ||
243 | depends on MIKROTIK_RB532 | ||
244 | depends on GPIOLIB && GENERIC_GPIO | ||
245 | select INPUT_POLLDEV | ||
246 | help | ||
247 | Say Y here if you want support for the S1 button built into | ||
248 | Mikrotik's Routerboard 532. | ||
249 | |||
250 | To compile this driver as a module, choose M here: the | ||
251 | module will be called rb532_button. | ||
252 | |||
230 | endif | 253 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index bb62e6efacf3..eb3f407baedf 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -4,21 +4,23 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 7 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
8 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | ||
9 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | ||
10 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | ||
11 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | ||
12 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | ||
13 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | ||
14 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
15 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
17 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | ||
18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | ||
19 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 11 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | ||
20 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 13 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
21 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 14 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
22 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 15 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
23 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 16 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
24 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 17 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
18 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | ||
19 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | ||
20 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | ||
21 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | ||
22 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | ||
23 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | ||
24 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | ||
25 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | ||
26 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 3c9988dc0e9f..922c05141585 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -31,12 +31,73 @@ MODULE_LICENSE("GPL"); | |||
31 | * newly configured "channel". | 31 | * newly configured "channel". |
32 | */ | 32 | */ |
33 | 33 | ||
34 | static unsigned int channel_mask = 0xFFFF; | 34 | enum { |
35 | module_param(channel_mask, uint, 0644); | 35 | ATI_REMOTE2_MAX_CHANNEL_MASK = 0xFFFF, |
36 | ATI_REMOTE2_MAX_MODE_MASK = 0x1F, | ||
37 | }; | ||
38 | |||
39 | static int ati_remote2_set_mask(const char *val, | ||
40 | struct kernel_param *kp, unsigned int max) | ||
41 | { | ||
42 | unsigned long mask; | ||
43 | int ret; | ||
44 | |||
45 | if (!val) | ||
46 | return -EINVAL; | ||
47 | |||
48 | ret = strict_strtoul(val, 0, &mask); | ||
49 | if (ret) | ||
50 | return ret; | ||
51 | |||
52 | if (mask & ~max) | ||
53 | return -EINVAL; | ||
54 | |||
55 | *(unsigned int *)kp->arg = mask; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int ati_remote2_set_channel_mask(const char *val, | ||
61 | struct kernel_param *kp) | ||
62 | { | ||
63 | pr_debug("%s()\n", __func__); | ||
64 | |||
65 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); | ||
66 | } | ||
67 | |||
68 | static int ati_remote2_get_channel_mask(char *buffer, struct kernel_param *kp) | ||
69 | { | ||
70 | pr_debug("%s()\n", __func__); | ||
71 | |||
72 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); | ||
73 | } | ||
74 | |||
75 | static int ati_remote2_set_mode_mask(const char *val, struct kernel_param *kp) | ||
76 | { | ||
77 | pr_debug("%s()\n", __func__); | ||
78 | |||
79 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); | ||
80 | } | ||
81 | |||
82 | static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | ||
83 | { | ||
84 | pr_debug("%s()\n", __func__); | ||
85 | |||
86 | return sprintf(buffer, "0x%02x", *(unsigned int *)kp->arg); | ||
87 | } | ||
88 | |||
89 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; | ||
90 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) | ||
91 | #define param_set_channel_mask ati_remote2_set_channel_mask | ||
92 | #define param_get_channel_mask ati_remote2_get_channel_mask | ||
93 | module_param(channel_mask, channel_mask, 0644); | ||
36 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 94 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); |
37 | 95 | ||
38 | static unsigned int mode_mask = 0x1F; | 96 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; |
39 | module_param(mode_mask, uint, 0644); | 97 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) |
98 | #define param_set_mode_mask ati_remote2_set_mode_mask | ||
99 | #define param_get_mode_mask ati_remote2_get_mode_mask | ||
100 | module_param(mode_mask, mode_mask, 0644); | ||
40 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 101 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
41 | 102 | ||
42 | static struct usb_device_id ati_remote2_id_table[] = { | 103 | static struct usb_device_id ati_remote2_id_table[] = { |
@@ -133,12 +194,18 @@ struct ati_remote2 { | |||
133 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; | 194 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; |
134 | 195 | ||
135 | unsigned int flags; | 196 | unsigned int flags; |
197 | |||
198 | unsigned int channel_mask; | ||
199 | unsigned int mode_mask; | ||
136 | }; | 200 | }; |
137 | 201 | ||
138 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | 202 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); |
139 | static void ati_remote2_disconnect(struct usb_interface *interface); | 203 | static void ati_remote2_disconnect(struct usb_interface *interface); |
140 | static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); | 204 | static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); |
141 | static int ati_remote2_resume(struct usb_interface *interface); | 205 | static int ati_remote2_resume(struct usb_interface *interface); |
206 | static int ati_remote2_reset_resume(struct usb_interface *interface); | ||
207 | static int ati_remote2_pre_reset(struct usb_interface *interface); | ||
208 | static int ati_remote2_post_reset(struct usb_interface *interface); | ||
142 | 209 | ||
143 | static struct usb_driver ati_remote2_driver = { | 210 | static struct usb_driver ati_remote2_driver = { |
144 | .name = "ati_remote2", | 211 | .name = "ati_remote2", |
@@ -147,6 +214,9 @@ static struct usb_driver ati_remote2_driver = { | |||
147 | .id_table = ati_remote2_id_table, | 214 | .id_table = ati_remote2_id_table, |
148 | .suspend = ati_remote2_suspend, | 215 | .suspend = ati_remote2_suspend, |
149 | .resume = ati_remote2_resume, | 216 | .resume = ati_remote2_resume, |
217 | .reset_resume = ati_remote2_reset_resume, | ||
218 | .pre_reset = ati_remote2_pre_reset, | ||
219 | .post_reset = ati_remote2_post_reset, | ||
150 | .supports_autosuspend = 1, | 220 | .supports_autosuspend = 1, |
151 | }; | 221 | }; |
152 | 222 | ||
@@ -238,7 +308,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
238 | 308 | ||
239 | channel = data[0] >> 4; | 309 | channel = data[0] >> 4; |
240 | 310 | ||
241 | if (!((1 << channel) & channel_mask)) | 311 | if (!((1 << channel) & ar2->channel_mask)) |
242 | return; | 312 | return; |
243 | 313 | ||
244 | mode = data[0] & 0x0F; | 314 | mode = data[0] & 0x0F; |
@@ -250,7 +320,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
250 | return; | 320 | return; |
251 | } | 321 | } |
252 | 322 | ||
253 | if (!((1 << mode) & mode_mask)) | 323 | if (!((1 << mode) & ar2->mode_mask)) |
254 | return; | 324 | return; |
255 | 325 | ||
256 | input_event(idev, EV_REL, REL_X, (s8) data[1]); | 326 | input_event(idev, EV_REL, REL_X, (s8) data[1]); |
@@ -277,7 +347,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
277 | 347 | ||
278 | channel = data[0] >> 4; | 348 | channel = data[0] >> 4; |
279 | 349 | ||
280 | if (!((1 << channel) & channel_mask)) | 350 | if (!((1 << channel) & ar2->channel_mask)) |
281 | return; | 351 | return; |
282 | 352 | ||
283 | mode = data[0] & 0x0F; | 353 | mode = data[0] & 0x0F; |
@@ -305,7 +375,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
305 | ar2->mode = mode; | 375 | ar2->mode = mode; |
306 | } | 376 | } |
307 | 377 | ||
308 | if (!((1 << mode) & mode_mask)) | 378 | if (!((1 << mode) & ar2->mode_mask)) |
309 | return; | 379 | return; |
310 | 380 | ||
311 | index = ati_remote2_lookup(hw_code); | 381 | index = ati_remote2_lookup(hw_code); |
@@ -410,7 +480,7 @@ static int ati_remote2_getkeycode(struct input_dev *idev, | |||
410 | int index, mode; | 480 | int index, mode; |
411 | 481 | ||
412 | mode = scancode >> 8; | 482 | mode = scancode >> 8; |
413 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | 483 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
414 | return -EINVAL; | 484 | return -EINVAL; |
415 | 485 | ||
416 | index = ati_remote2_lookup(scancode & 0xFF); | 486 | index = ati_remote2_lookup(scancode & 0xFF); |
@@ -427,7 +497,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc | |||
427 | int index, mode, old_keycode; | 497 | int index, mode, old_keycode; |
428 | 498 | ||
429 | mode = scancode >> 8; | 499 | mode = scancode >> 8; |
430 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | 500 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
431 | return -EINVAL; | 501 | return -EINVAL; |
432 | 502 | ||
433 | index = ati_remote2_lookup(scancode & 0xFF); | 503 | index = ati_remote2_lookup(scancode & 0xFF); |
@@ -550,7 +620,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | |||
550 | } | 620 | } |
551 | } | 621 | } |
552 | 622 | ||
553 | static int ati_remote2_setup(struct ati_remote2 *ar2) | 623 | static int ati_remote2_setup(struct ati_remote2 *ar2, unsigned int ch_mask) |
554 | { | 624 | { |
555 | int r, i, channel; | 625 | int r, i, channel; |
556 | 626 | ||
@@ -565,8 +635,8 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) | |||
565 | 635 | ||
566 | channel = 0; | 636 | channel = 0; |
567 | for (i = 0; i < 16; i++) { | 637 | for (i = 0; i < 16; i++) { |
568 | if ((1 << i) & channel_mask) { | 638 | if ((1 << i) & ch_mask) { |
569 | if (!(~(1 << i) & 0xFFFF & channel_mask)) | 639 | if (!(~(1 << i) & ch_mask)) |
570 | channel = i + 1; | 640 | channel = i + 1; |
571 | break; | 641 | break; |
572 | } | 642 | } |
@@ -585,6 +655,99 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) | |||
585 | return 0; | 655 | return 0; |
586 | } | 656 | } |
587 | 657 | ||
658 | static ssize_t ati_remote2_show_channel_mask(struct device *dev, | ||
659 | struct device_attribute *attr, | ||
660 | char *buf) | ||
661 | { | ||
662 | struct usb_device *udev = to_usb_device(dev); | ||
663 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
664 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
665 | |||
666 | return sprintf(buf, "0x%04x\n", ar2->channel_mask); | ||
667 | } | ||
668 | |||
669 | static ssize_t ati_remote2_store_channel_mask(struct device *dev, | ||
670 | struct device_attribute *attr, | ||
671 | const char *buf, size_t count) | ||
672 | { | ||
673 | struct usb_device *udev = to_usb_device(dev); | ||
674 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
675 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
676 | unsigned long mask; | ||
677 | int r; | ||
678 | |||
679 | if (strict_strtoul(buf, 0, &mask)) | ||
680 | return -EINVAL; | ||
681 | |||
682 | if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK) | ||
683 | return -EINVAL; | ||
684 | |||
685 | r = usb_autopm_get_interface(ar2->intf[0]); | ||
686 | if (r) { | ||
687 | dev_err(&ar2->intf[0]->dev, | ||
688 | "%s(): usb_autopm_get_interface() = %d\n", __func__, r); | ||
689 | return r; | ||
690 | } | ||
691 | |||
692 | mutex_lock(&ati_remote2_mutex); | ||
693 | |||
694 | if (mask != ar2->channel_mask && !ati_remote2_setup(ar2, mask)) | ||
695 | ar2->channel_mask = mask; | ||
696 | |||
697 | mutex_unlock(&ati_remote2_mutex); | ||
698 | |||
699 | usb_autopm_put_interface(ar2->intf[0]); | ||
700 | |||
701 | return count; | ||
702 | } | ||
703 | |||
704 | static ssize_t ati_remote2_show_mode_mask(struct device *dev, | ||
705 | struct device_attribute *attr, | ||
706 | char *buf) | ||
707 | { | ||
708 | struct usb_device *udev = to_usb_device(dev); | ||
709 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
710 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
711 | |||
712 | return sprintf(buf, "0x%02x\n", ar2->mode_mask); | ||
713 | } | ||
714 | |||
715 | static ssize_t ati_remote2_store_mode_mask(struct device *dev, | ||
716 | struct device_attribute *attr, | ||
717 | const char *buf, size_t count) | ||
718 | { | ||
719 | struct usb_device *udev = to_usb_device(dev); | ||
720 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
721 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
722 | unsigned long mask; | ||
723 | |||
724 | if (strict_strtoul(buf, 0, &mask)) | ||
725 | return -EINVAL; | ||
726 | |||
727 | if (mask & ~ATI_REMOTE2_MAX_MODE_MASK) | ||
728 | return -EINVAL; | ||
729 | |||
730 | ar2->mode_mask = mask; | ||
731 | |||
732 | return count; | ||
733 | } | ||
734 | |||
735 | static DEVICE_ATTR(channel_mask, 0644, ati_remote2_show_channel_mask, | ||
736 | ati_remote2_store_channel_mask); | ||
737 | |||
738 | static DEVICE_ATTR(mode_mask, 0644, ati_remote2_show_mode_mask, | ||
739 | ati_remote2_store_mode_mask); | ||
740 | |||
741 | static struct attribute *ati_remote2_attrs[] = { | ||
742 | &dev_attr_channel_mask.attr, | ||
743 | &dev_attr_mode_mask.attr, | ||
744 | NULL, | ||
745 | }; | ||
746 | |||
747 | static struct attribute_group ati_remote2_attr_group = { | ||
748 | .attrs = ati_remote2_attrs, | ||
749 | }; | ||
750 | |||
588 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) | 751 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) |
589 | { | 752 | { |
590 | struct usb_device *udev = interface_to_usbdev(interface); | 753 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -615,7 +778,10 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
615 | if (r) | 778 | if (r) |
616 | goto fail2; | 779 | goto fail2; |
617 | 780 | ||
618 | r = ati_remote2_setup(ar2); | 781 | ar2->channel_mask = channel_mask; |
782 | ar2->mode_mask = mode_mask; | ||
783 | |||
784 | r = ati_remote2_setup(ar2, ar2->channel_mask); | ||
619 | if (r) | 785 | if (r) |
620 | goto fail2; | 786 | goto fail2; |
621 | 787 | ||
@@ -624,19 +790,24 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
624 | 790 | ||
625 | strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); | 791 | strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); |
626 | 792 | ||
627 | r = ati_remote2_input_init(ar2); | 793 | r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); |
628 | if (r) | 794 | if (r) |
629 | goto fail2; | 795 | goto fail2; |
630 | 796 | ||
797 | r = ati_remote2_input_init(ar2); | ||
798 | if (r) | ||
799 | goto fail3; | ||
800 | |||
631 | usb_set_intfdata(interface, ar2); | 801 | usb_set_intfdata(interface, ar2); |
632 | 802 | ||
633 | interface->needs_remote_wakeup = 1; | 803 | interface->needs_remote_wakeup = 1; |
634 | 804 | ||
635 | return 0; | 805 | return 0; |
636 | 806 | ||
807 | fail3: | ||
808 | sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); | ||
637 | fail2: | 809 | fail2: |
638 | ati_remote2_urb_cleanup(ar2); | 810 | ati_remote2_urb_cleanup(ar2); |
639 | |||
640 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 811 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); |
641 | fail1: | 812 | fail1: |
642 | kfree(ar2); | 813 | kfree(ar2); |
@@ -657,6 +828,8 @@ static void ati_remote2_disconnect(struct usb_interface *interface) | |||
657 | 828 | ||
658 | input_unregister_device(ar2->idev); | 829 | input_unregister_device(ar2->idev); |
659 | 830 | ||
831 | sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group); | ||
832 | |||
660 | ati_remote2_urb_cleanup(ar2); | 833 | ati_remote2_urb_cleanup(ar2); |
661 | 834 | ||
662 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 835 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); |
@@ -715,6 +888,78 @@ static int ati_remote2_resume(struct usb_interface *interface) | |||
715 | return r; | 888 | return r; |
716 | } | 889 | } |
717 | 890 | ||
891 | static int ati_remote2_reset_resume(struct usb_interface *interface) | ||
892 | { | ||
893 | struct ati_remote2 *ar2; | ||
894 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
895 | int r = 0; | ||
896 | |||
897 | if (alt->desc.bInterfaceNumber) | ||
898 | return 0; | ||
899 | |||
900 | ar2 = usb_get_intfdata(interface); | ||
901 | |||
902 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
903 | |||
904 | mutex_lock(&ati_remote2_mutex); | ||
905 | |||
906 | r = ati_remote2_setup(ar2, ar2->channel_mask); | ||
907 | if (r) | ||
908 | goto out; | ||
909 | |||
910 | if (ar2->flags & ATI_REMOTE2_OPENED) | ||
911 | r = ati_remote2_submit_urbs(ar2); | ||
912 | |||
913 | if (!r) | ||
914 | ar2->flags &= ~ATI_REMOTE2_SUSPENDED; | ||
915 | |||
916 | out: | ||
917 | mutex_unlock(&ati_remote2_mutex); | ||
918 | |||
919 | return r; | ||
920 | } | ||
921 | |||
922 | static int ati_remote2_pre_reset(struct usb_interface *interface) | ||
923 | { | ||
924 | struct ati_remote2 *ar2; | ||
925 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
926 | |||
927 | if (alt->desc.bInterfaceNumber) | ||
928 | return 0; | ||
929 | |||
930 | ar2 = usb_get_intfdata(interface); | ||
931 | |||
932 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
933 | |||
934 | mutex_lock(&ati_remote2_mutex); | ||
935 | |||
936 | if (ar2->flags == ATI_REMOTE2_OPENED) | ||
937 | ati_remote2_kill_urbs(ar2); | ||
938 | |||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int ati_remote2_post_reset(struct usb_interface *interface) | ||
943 | { | ||
944 | struct ati_remote2 *ar2; | ||
945 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
946 | int r = 0; | ||
947 | |||
948 | if (alt->desc.bInterfaceNumber) | ||
949 | return 0; | ||
950 | |||
951 | ar2 = usb_get_intfdata(interface); | ||
952 | |||
953 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
954 | |||
955 | if (ar2->flags == ATI_REMOTE2_OPENED) | ||
956 | r = ati_remote2_submit_urbs(ar2); | ||
957 | |||
958 | mutex_unlock(&ati_remote2_mutex); | ||
959 | |||
960 | return r; | ||
961 | } | ||
962 | |||
718 | static int __init ati_remote2_init(void) | 963 | static int __init ati_remote2_init(void) |
719 | { | 964 | { |
720 | int r; | 965 | int r; |
diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c new file mode 100644 index 000000000000..e2c7f622a0b5 --- /dev/null +++ b/drivers/input/misc/rb532_button.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * Support for the S1 button on Routerboard 532 | ||
3 | * | ||
4 | * Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org> | ||
5 | */ | ||
6 | |||
7 | #include <linux/input-polldev.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | |||
11 | #include <asm/mach-rc32434/gpio.h> | ||
12 | #include <asm/mach-rc32434/rb.h> | ||
13 | |||
14 | #define DRV_NAME "rb532-button" | ||
15 | |||
16 | #define RB532_BTN_RATE 100 /* msec */ | ||
17 | #define RB532_BTN_KSYM BTN_0 | ||
18 | |||
19 | /* The S1 button state is provided by GPIO pin 1. But as this | ||
20 | * pin is also used for uart input as alternate function, the | ||
21 | * operational modes must be switched first: | ||
22 | * 1) disable uart using set_latch_u5() | ||
23 | * 2) turn off alternate function implicitly through | ||
24 | * gpio_direction_input() | ||
25 | * 3) read the GPIO's current value | ||
26 | * 4) undo step 2 by enabling alternate function (in this | ||
27 | * mode the GPIO direction is fixed, so no change needed) | ||
28 | * 5) turn on uart again | ||
29 | * The GPIO value occurs to be inverted, so pin high means | ||
30 | * button is not pressed. | ||
31 | */ | ||
32 | static bool rb532_button_pressed(void) | ||
33 | { | ||
34 | int val; | ||
35 | |||
36 | set_latch_u5(0, LO_FOFF); | ||
37 | gpio_direction_input(GPIO_BTN_S1); | ||
38 | |||
39 | val = gpio_get_value(GPIO_BTN_S1); | ||
40 | |||
41 | rb532_gpio_set_func(GPIO_BTN_S1); | ||
42 | set_latch_u5(LO_FOFF, 0); | ||
43 | |||
44 | return !val; | ||
45 | } | ||
46 | |||
47 | static void rb532_button_poll(struct input_polled_dev *poll_dev) | ||
48 | { | ||
49 | input_report_key(poll_dev->input, RB532_BTN_KSYM, | ||
50 | rb532_button_pressed()); | ||
51 | input_sync(poll_dev->input); | ||
52 | } | ||
53 | |||
54 | static int __devinit rb532_button_probe(struct platform_device *pdev) | ||
55 | { | ||
56 | struct input_polled_dev *poll_dev; | ||
57 | int error; | ||
58 | |||
59 | poll_dev = input_allocate_polled_device(); | ||
60 | if (!poll_dev) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | poll_dev->poll = rb532_button_poll; | ||
64 | poll_dev->poll_interval = RB532_BTN_RATE; | ||
65 | |||
66 | poll_dev->input->name = "rb532 button"; | ||
67 | poll_dev->input->phys = "rb532/button0"; | ||
68 | poll_dev->input->id.bustype = BUS_HOST; | ||
69 | poll_dev->input->dev.parent = &pdev->dev; | ||
70 | |||
71 | dev_set_drvdata(&pdev->dev, poll_dev); | ||
72 | |||
73 | input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM); | ||
74 | |||
75 | error = input_register_polled_device(poll_dev); | ||
76 | if (error) { | ||
77 | input_free_polled_device(poll_dev); | ||
78 | return error; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int __devexit rb532_button_remove(struct platform_device *pdev) | ||
85 | { | ||
86 | struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev); | ||
87 | |||
88 | input_unregister_polled_device(poll_dev); | ||
89 | input_free_polled_device(poll_dev); | ||
90 | dev_set_drvdata(&pdev->dev, NULL); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static struct platform_driver rb532_button_driver = { | ||
96 | .probe = rb532_button_probe, | ||
97 | .remove = __devexit_p(rb532_button_remove), | ||
98 | .driver = { | ||
99 | .name = DRV_NAME, | ||
100 | .owner = THIS_MODULE, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | static int __init rb532_button_init(void) | ||
105 | { | ||
106 | return platform_driver_register(&rb532_button_driver); | ||
107 | } | ||
108 | |||
109 | static void __exit rb532_button_exit(void) | ||
110 | { | ||
111 | platform_driver_unregister(&rb532_button_driver); | ||
112 | } | ||
113 | |||
114 | module_init(rb532_button_init); | ||
115 | module_exit(rb532_button_exit); | ||
116 | |||
117 | MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); | ||
118 | MODULE_LICENSE("GPL"); | ||
119 | MODULE_DESCRIPTION("Support for S1 button on Routerboard 532"); | ||
120 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c new file mode 100644 index 000000000000..5bb3ab51b8c6 --- /dev/null +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * rotary_encoder.c | ||
3 | * | ||
4 | * (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
5 | * | ||
6 | * state machine code inspired by code from Tim Ruetz | ||
7 | * | ||
8 | * A generic driver for rotary encoders connected to GPIO lines. | ||
9 | * See file:Documentation/input/rotary_encoder.txt for more information | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/rotary_encoder.h> | ||
25 | |||
26 | #define DRV_NAME "rotary-encoder" | ||
27 | |||
28 | struct rotary_encoder { | ||
29 | unsigned int irq_a; | ||
30 | unsigned int irq_b; | ||
31 | unsigned int pos; | ||
32 | unsigned int armed; | ||
33 | unsigned int dir; | ||
34 | struct input_dev *input; | ||
35 | struct rotary_encoder_platform_data *pdata; | ||
36 | }; | ||
37 | |||
38 | static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | ||
39 | { | ||
40 | struct rotary_encoder *encoder = dev_id; | ||
41 | struct rotary_encoder_platform_data *pdata = encoder->pdata; | ||
42 | int a = !!gpio_get_value(pdata->gpio_a); | ||
43 | int b = !!gpio_get_value(pdata->gpio_b); | ||
44 | int state; | ||
45 | |||
46 | a ^= pdata->inverted_a; | ||
47 | b ^= pdata->inverted_b; | ||
48 | state = (a << 1) | b; | ||
49 | |||
50 | switch (state) { | ||
51 | |||
52 | case 0x0: | ||
53 | if (!encoder->armed) | ||
54 | break; | ||
55 | |||
56 | if (encoder->dir) { | ||
57 | /* turning counter-clockwise */ | ||
58 | encoder->pos += pdata->steps; | ||
59 | encoder->pos--; | ||
60 | encoder->pos %= pdata->steps; | ||
61 | } else { | ||
62 | /* turning clockwise */ | ||
63 | encoder->pos++; | ||
64 | encoder->pos %= pdata->steps; | ||
65 | } | ||
66 | |||
67 | input_report_abs(encoder->input, pdata->axis, encoder->pos); | ||
68 | input_sync(encoder->input); | ||
69 | |||
70 | encoder->armed = 0; | ||
71 | break; | ||
72 | |||
73 | case 0x1: | ||
74 | case 0x2: | ||
75 | if (encoder->armed) | ||
76 | encoder->dir = state - 1; | ||
77 | break; | ||
78 | |||
79 | case 0x3: | ||
80 | encoder->armed = 1; | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | return IRQ_HANDLED; | ||
85 | } | ||
86 | |||
87 | static int __devinit rotary_encoder_probe(struct platform_device *pdev) | ||
88 | { | ||
89 | struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; | ||
90 | struct rotary_encoder *encoder; | ||
91 | struct input_dev *input; | ||
92 | int err; | ||
93 | |||
94 | if (!pdata || !pdata->steps) { | ||
95 | dev_err(&pdev->dev, "invalid platform data\n"); | ||
96 | return -ENOENT; | ||
97 | } | ||
98 | |||
99 | encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); | ||
100 | input = input_allocate_device(); | ||
101 | if (!encoder || !input) { | ||
102 | dev_err(&pdev->dev, "failed to allocate memory for device\n"); | ||
103 | err = -ENOMEM; | ||
104 | goto exit_free_mem; | ||
105 | } | ||
106 | |||
107 | encoder->input = input; | ||
108 | encoder->pdata = pdata; | ||
109 | encoder->irq_a = gpio_to_irq(pdata->gpio_a); | ||
110 | encoder->irq_b = gpio_to_irq(pdata->gpio_b); | ||
111 | |||
112 | /* create and register the input driver */ | ||
113 | input->name = pdev->name; | ||
114 | input->id.bustype = BUS_HOST; | ||
115 | input->dev.parent = &pdev->dev; | ||
116 | input->evbit[0] = BIT_MASK(EV_ABS); | ||
117 | input_set_abs_params(encoder->input, | ||
118 | pdata->axis, 0, pdata->steps, 0, 1); | ||
119 | |||
120 | err = input_register_device(input); | ||
121 | if (err) { | ||
122 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
123 | goto exit_free_mem; | ||
124 | } | ||
125 | |||
126 | /* request the GPIOs */ | ||
127 | err = gpio_request(pdata->gpio_a, DRV_NAME); | ||
128 | if (err) { | ||
129 | dev_err(&pdev->dev, "unable to request GPIO %d\n", | ||
130 | pdata->gpio_a); | ||
131 | goto exit_unregister_input; | ||
132 | } | ||
133 | |||
134 | err = gpio_request(pdata->gpio_b, DRV_NAME); | ||
135 | if (err) { | ||
136 | dev_err(&pdev->dev, "unable to request GPIO %d\n", | ||
137 | pdata->gpio_b); | ||
138 | goto exit_free_gpio_a; | ||
139 | } | ||
140 | |||
141 | /* request the IRQs */ | ||
142 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, | ||
143 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, | ||
144 | DRV_NAME, encoder); | ||
145 | if (err) { | ||
146 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | ||
147 | encoder->irq_a); | ||
148 | goto exit_free_gpio_b; | ||
149 | } | ||
150 | |||
151 | err = request_irq(encoder->irq_b, &rotary_encoder_irq, | ||
152 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, | ||
153 | DRV_NAME, encoder); | ||
154 | if (err) { | ||
155 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | ||
156 | encoder->irq_b); | ||
157 | goto exit_free_irq_a; | ||
158 | } | ||
159 | |||
160 | platform_set_drvdata(pdev, encoder); | ||
161 | |||
162 | return 0; | ||
163 | |||
164 | exit_free_irq_a: | ||
165 | free_irq(encoder->irq_a, encoder); | ||
166 | exit_free_gpio_b: | ||
167 | gpio_free(pdata->gpio_b); | ||
168 | exit_free_gpio_a: | ||
169 | gpio_free(pdata->gpio_a); | ||
170 | exit_unregister_input: | ||
171 | input_unregister_device(input); | ||
172 | input = NULL; /* so we don't try to free it */ | ||
173 | exit_free_mem: | ||
174 | input_free_device(input); | ||
175 | kfree(encoder); | ||
176 | return err; | ||
177 | } | ||
178 | |||
179 | static int __devexit rotary_encoder_remove(struct platform_device *pdev) | ||
180 | { | ||
181 | struct rotary_encoder *encoder = platform_get_drvdata(pdev); | ||
182 | struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; | ||
183 | |||
184 | free_irq(encoder->irq_a, encoder); | ||
185 | free_irq(encoder->irq_b, encoder); | ||
186 | gpio_free(pdata->gpio_a); | ||
187 | gpio_free(pdata->gpio_b); | ||
188 | input_unregister_device(encoder->input); | ||
189 | platform_set_drvdata(pdev, NULL); | ||
190 | kfree(encoder); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static struct platform_driver rotary_encoder_driver = { | ||
196 | .probe = rotary_encoder_probe, | ||
197 | .remove = __devexit_p(rotary_encoder_remove), | ||
198 | .driver = { | ||
199 | .name = DRV_NAME, | ||
200 | .owner = THIS_MODULE, | ||
201 | } | ||
202 | }; | ||
203 | |||
204 | static int __init rotary_encoder_init(void) | ||
205 | { | ||
206 | return platform_driver_register(&rotary_encoder_driver); | ||
207 | } | ||
208 | |||
209 | static void __exit rotary_encoder_exit(void) | ||
210 | { | ||
211 | platform_driver_unregister(&rotary_encoder_driver); | ||
212 | } | ||
213 | |||
214 | module_init(rotary_encoder_init); | ||
215 | module_exit(rotary_encoder_exit); | ||
216 | |||
217 | MODULE_ALIAS("platform:" DRV_NAME); | ||
218 | MODULE_DESCRIPTION("GPIO rotary encoder driver"); | ||
219 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
220 | MODULE_LICENSE("GPL v2"); | ||
221 | |||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 4f38e6f7dfdd..c66cc3d08c2f 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -292,4 +292,15 @@ config MOUSE_PXA930_TRKBALL | |||
292 | help | 292 | help |
293 | Say Y here to support PXA930 Trackball mouse. | 293 | Say Y here to support PXA930 Trackball mouse. |
294 | 294 | ||
295 | config MOUSE_MAPLE | ||
296 | tristate "Maple mouse (for the Dreamcast)" | ||
297 | depends on MAPLE | ||
298 | help | ||
299 | This driver supports the Maple mouse on the SEGA Dreamcast. | ||
300 | |||
301 | Most Dreamcast users, who have a mouse, will say Y here. | ||
302 | |||
303 | To compile this driver as a module choose M here: the module will be | ||
304 | called maplemouse. | ||
305 | |||
295 | endif | 306 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8c8a1f236e28..472189468d67 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -6,18 +6,19 @@ | |||
6 | 6 | ||
7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
8 | obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | 8 | obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o |
9 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | ||
10 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
11 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o |
11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | ||
12 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 13 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 14 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
15 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | ||
14 | obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o | 16 | obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o |
15 | obj-$(CONFIG_MOUSE_PS2) += psmouse.o | 17 | obj-$(CONFIG_MOUSE_PS2) += psmouse.o |
16 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o | 18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o |
19 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | ||
17 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | 20 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o |
18 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
19 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 21 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
20 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | ||
21 | 22 | ||
22 | psmouse-objs := psmouse-base.o synaptics.o | 23 | psmouse-objs := psmouse-base.o synaptics.o |
23 | 24 | ||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 55cd0fa68339..a1ad2f1a7bb3 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -472,7 +472,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | |||
472 | return -EIO; | 472 | return -EIO; |
473 | } | 473 | } |
474 | 474 | ||
475 | hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]); | 475 | hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); |
476 | 476 | ||
477 | /* HGPK signature: 0x67, 0x00, 0x<model> */ | 477 | /* HGPK signature: 0x67, 0x00, 0x<model> */ |
478 | if (param[0] != 0x67 || param[1] != 0x00) | 478 | if (param[0] != 0x67 || param[1] != 0x00) |
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c new file mode 100644 index 000000000000..d196abfb68bc --- /dev/null +++ b/drivers/input/mouse/maplemouse.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * SEGA Dreamcast mouse driver | ||
3 | * Based on drivers/usb/usbmouse.c | ||
4 | * | ||
5 | * Copyright Yaegashi Takeshi, 2001 | ||
6 | * Adrian McMenamin, 2008 | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/maple.h> | ||
16 | |||
17 | MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); | ||
18 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); | ||
19 | MODULE_LICENSE("GPL"); | ||
20 | |||
21 | struct dc_mouse { | ||
22 | struct input_dev *dev; | ||
23 | struct maple_device *mdev; | ||
24 | }; | ||
25 | |||
26 | static void dc_mouse_callback(struct mapleq *mq) | ||
27 | { | ||
28 | int buttons, relx, rely, relz; | ||
29 | struct maple_device *mapledev = mq->dev; | ||
30 | struct dc_mouse *mse = maple_get_drvdata(mapledev); | ||
31 | struct input_dev *dev = mse->dev; | ||
32 | unsigned char *res = mq->recvbuf; | ||
33 | |||
34 | buttons = ~res[8]; | ||
35 | relx = *(unsigned short *)(res + 12) - 512; | ||
36 | rely = *(unsigned short *)(res + 14) - 512; | ||
37 | relz = *(unsigned short *)(res + 16) - 512; | ||
38 | |||
39 | input_report_key(dev, BTN_LEFT, buttons & 4); | ||
40 | input_report_key(dev, BTN_MIDDLE, buttons & 9); | ||
41 | input_report_key(dev, BTN_RIGHT, buttons & 2); | ||
42 | input_report_rel(dev, REL_X, relx); | ||
43 | input_report_rel(dev, REL_Y, rely); | ||
44 | input_report_rel(dev, REL_WHEEL, relz); | ||
45 | input_sync(dev); | ||
46 | } | ||
47 | |||
48 | static int dc_mouse_open(struct input_dev *dev) | ||
49 | { | ||
50 | struct dc_mouse *mse = dev->dev.platform_data; | ||
51 | |||
52 | maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, | ||
53 | MAPLE_FUNC_MOUSE); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static void dc_mouse_close(struct input_dev *dev) | ||
59 | { | ||
60 | struct dc_mouse *mse = dev->dev.platform_data; | ||
61 | |||
62 | maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, | ||
63 | MAPLE_FUNC_MOUSE); | ||
64 | } | ||
65 | |||
66 | |||
67 | static int __devinit probe_maple_mouse(struct device *dev) | ||
68 | { | ||
69 | struct maple_device *mdev = to_maple_dev(dev); | ||
70 | struct maple_driver *mdrv = to_maple_driver(dev->driver); | ||
71 | struct input_dev *input_dev; | ||
72 | struct dc_mouse *mse; | ||
73 | int error; | ||
74 | |||
75 | mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); | ||
76 | input_dev = input_allocate_device(); | ||
77 | |||
78 | if (!mse || !input_dev) { | ||
79 | error = -ENOMEM; | ||
80 | goto fail; | ||
81 | } | ||
82 | |||
83 | mse->dev = input_dev; | ||
84 | mse->mdev = mdev; | ||
85 | |||
86 | input_set_drvdata(input_dev, mse); | ||
87 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | ||
88 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | | ||
89 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | ||
90 | input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | | ||
91 | BIT_MASK(REL_WHEEL); | ||
92 | input_dev->name = mdev->product_name; | ||
93 | input_dev->id.bustype = BUS_HOST; | ||
94 | input_dev->open = dc_mouse_open; | ||
95 | input_dev->close = dc_mouse_close; | ||
96 | |||
97 | mdev->driver = mdrv; | ||
98 | maple_set_drvdata(mdev, mse); | ||
99 | |||
100 | error = input_register_device(input_dev); | ||
101 | if (error) | ||
102 | goto fail; | ||
103 | |||
104 | return 0; | ||
105 | |||
106 | fail: | ||
107 | input_free_device(input_dev); | ||
108 | maple_set_drvdata(mdev, NULL); | ||
109 | kfree(mse); | ||
110 | mdev->driver = NULL; | ||
111 | return error; | ||
112 | } | ||
113 | |||
114 | static int __devexit remove_maple_mouse(struct device *dev) | ||
115 | { | ||
116 | struct maple_device *mdev = to_maple_dev(dev); | ||
117 | struct dc_mouse *mse = maple_get_drvdata(mdev); | ||
118 | |||
119 | mdev->callback = NULL; | ||
120 | input_unregister_device(mse->dev); | ||
121 | maple_set_drvdata(mdev, NULL); | ||
122 | kfree(mse); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static struct maple_driver dc_mouse_driver = { | ||
128 | .function = MAPLE_FUNC_MOUSE, | ||
129 | .drv = { | ||
130 | .name = "Dreamcast_mouse", | ||
131 | .probe = probe_maple_mouse, | ||
132 | .remove = __devexit_p(remove_maple_mouse), | ||
133 | }, | ||
134 | }; | ||
135 | |||
136 | static int __init dc_mouse_init(void) | ||
137 | { | ||
138 | return maple_driver_register(&dc_mouse_driver); | ||
139 | } | ||
140 | |||
141 | static void __exit dc_mouse_exit(void) | ||
142 | { | ||
143 | maple_driver_unregister(&dc_mouse_driver); | ||
144 | } | ||
145 | |||
146 | module_init(dc_mouse_init); | ||
147 | module_exit(dc_mouse_exit); | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index fd09c8df81f2..f63995f854ff 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -111,11 +111,8 @@ static int __init pc110pad_init(void) | |||
111 | struct pci_dev *dev; | 111 | struct pci_dev *dev; |
112 | int err; | 112 | int err; |
113 | 113 | ||
114 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); | 114 | if (!no_pci_devices()) |
115 | if (dev) { | ||
116 | pci_dev_put(dev); | ||
117 | return -ENODEV; | 115 | return -ENODEV; |
118 | } | ||
119 | 116 | ||
120 | if (!request_region(pc110pad_io, 4, "pc110pad")) { | 117 | if (!request_region(pc110pad_io, 4, "pc110pad")) { |
121 | printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", | 118 | printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6fa2deff7446..83ed2d56b924 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -151,6 +151,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
151 | DMI_MATCH(DMI_PRODUCT_VERSION, "01"), | 151 | DMI_MATCH(DMI_PRODUCT_VERSION, "01"), |
152 | }, | 152 | }, |
153 | }, | 153 | }, |
154 | { | ||
155 | .ident = "HP DV9700", | ||
156 | .matches = { | ||
157 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
158 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), | ||
159 | DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), | ||
160 | }, | ||
161 | }, | ||
154 | { } | 162 | { } |
155 | }; | 163 | }; |
156 | 164 | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index bb6486a8c070..b01fd61dadcc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -29,6 +29,51 @@ config TOUCHSCREEN_ADS7846 | |||
29 | To compile this driver as a module, choose M here: the | 29 | To compile this driver as a module, choose M here: the |
30 | module will be called ads7846. | 30 | module will be called ads7846. |
31 | 31 | ||
32 | config TOUCHSCREEN_AD7877 | ||
33 | tristate "AD7877 based touchscreens" | ||
34 | depends on SPI_MASTER | ||
35 | help | ||
36 | Say Y here if you have a touchscreen interface using the | ||
37 | AD7877 controller, and your board-specific initialization | ||
38 | code includes that in its table of SPI devices. | ||
39 | |||
40 | If unsure, say N (but it's safe to say "Y"). | ||
41 | |||
42 | To compile this driver as a module, choose M here: the | ||
43 | module will be called ad7877. | ||
44 | |||
45 | config TOUCHSCREEN_AD7879_I2C | ||
46 | tristate "AD7879 based touchscreens: AD7879-1 I2C Interface" | ||
47 | depends on I2C | ||
48 | select TOUCHSCREEN_AD7879 | ||
49 | help | ||
50 | Say Y here if you have a touchscreen interface using the | ||
51 | AD7879-1 controller, and your board-specific initialization | ||
52 | code includes that in its table of I2C devices. | ||
53 | |||
54 | If unsure, say N (but it's safe to say "Y"). | ||
55 | |||
56 | To compile this driver as a module, choose M here: the | ||
57 | module will be called ad7879. | ||
58 | |||
59 | config TOUCHSCREEN_AD7879_SPI | ||
60 | tristate "AD7879 based touchscreens: AD7879 SPI Interface" | ||
61 | depends on SPI_MASTER && TOUCHSCREEN_AD7879_I2C = n | ||
62 | select TOUCHSCREEN_AD7879 | ||
63 | help | ||
64 | Say Y here if you have a touchscreen interface using the | ||
65 | AD7879 controller, and your board-specific initialization | ||
66 | code includes that in its table of SPI devices. | ||
67 | |||
68 | If unsure, say N (but it's safe to say "Y"). | ||
69 | |||
70 | To compile this driver as a module, choose M here: the | ||
71 | module will be called ad7879. | ||
72 | |||
73 | config TOUCHSCREEN_AD7879 | ||
74 | tristate | ||
75 | default n | ||
76 | |||
32 | config TOUCHSCREEN_BITSY | 77 | config TOUCHSCREEN_BITSY |
33 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" | 78 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" |
34 | depends on SA1100_BITSY | 79 | depends on SA1100_BITSY |
@@ -308,6 +353,19 @@ config TOUCHSCREEN_WM97XX_MAINSTONE | |||
308 | To compile this driver as a module, choose M here: the | 353 | To compile this driver as a module, choose M here: the |
309 | module will be called mainstone-wm97xx. | 354 | module will be called mainstone-wm97xx. |
310 | 355 | ||
356 | config TOUCHSCREEN_WM97XX_ZYLONITE | ||
357 | tristate "Zylonite accelerated touch" | ||
358 | depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE | ||
359 | select TOUCHSCREEN_WM9713 | ||
360 | help | ||
361 | Say Y here for support for streaming mode with the touchscreen | ||
362 | on Zylonite systems. | ||
363 | |||
364 | If unsure, say N. | ||
365 | |||
366 | To compile this driver as a module, choose M here: the | ||
367 | module will be called zylonite-wm97xx. | ||
368 | |||
311 | config TOUCHSCREEN_USB_COMPOSITE | 369 | config TOUCHSCREEN_USB_COMPOSITE |
312 | tristate "USB Touchscreen Driver" | 370 | tristate "USB Touchscreen Driver" |
313 | depends on USB_ARCH_HAS_HCD | 371 | depends on USB_ARCH_HAS_HCD |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index d3375aff46fe..6700f7b9d165 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | wm97xx-ts-y := wm97xx-core.o | 7 | wm97xx-ts-y := wm97xx-core.o |
8 | 8 | ||
9 | obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o | ||
10 | obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | ||
9 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 11 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
10 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
11 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
@@ -34,3 +36,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o | |||
34 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o | 36 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o |
35 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o | 37 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o |
36 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 38 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
39 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | ||
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c new file mode 100644 index 000000000000..e4728a28f492 --- /dev/null +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -0,0 +1,844 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2008 Michael Hennerich, Analog Devices Inc. | ||
3 | * | ||
4 | * Description: AD7877 based touchscreen, sensor (ADCs), DAC and GPIO driver | ||
5 | * Based on: ads7846.c | ||
6 | * | ||
7 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, see the file COPYING, or write | ||
21 | * to the Free Software Foundation, Inc., | ||
22 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
23 | * | ||
24 | * History: | ||
25 | * Copyright (c) 2005 David Brownell | ||
26 | * Copyright (c) 2006 Nokia Corporation | ||
27 | * Various changes: Imre Deak <imre.deak@nokia.com> | ||
28 | * | ||
29 | * Using code from: | ||
30 | * - corgi_ts.c | ||
31 | * Copyright (C) 2004-2005 Richard Purdie | ||
32 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
33 | * Copyright (C) 2002 MontaVista Software | ||
34 | * Copyright (C) 2004 Texas Instruments | ||
35 | * Copyright (C) 2005 Dirk Behme | ||
36 | */ | ||
37 | |||
38 | |||
39 | #include <linux/device.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/input.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <linux/slab.h> | ||
45 | #include <linux/spi/spi.h> | ||
46 | #include <linux/spi/ad7877.h> | ||
47 | #include <asm/irq.h> | ||
48 | |||
49 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) | ||
50 | |||
51 | #define MAX_SPI_FREQ_HZ 20000000 | ||
52 | #define MAX_12BIT ((1<<12)-1) | ||
53 | |||
54 | #define AD7877_REG_ZEROS 0 | ||
55 | #define AD7877_REG_CTRL1 1 | ||
56 | #define AD7877_REG_CTRL2 2 | ||
57 | #define AD7877_REG_ALERT 3 | ||
58 | #define AD7877_REG_AUX1HIGH 4 | ||
59 | #define AD7877_REG_AUX1LOW 5 | ||
60 | #define AD7877_REG_BAT1HIGH 6 | ||
61 | #define AD7877_REG_BAT1LOW 7 | ||
62 | #define AD7877_REG_BAT2HIGH 8 | ||
63 | #define AD7877_REG_BAT2LOW 9 | ||
64 | #define AD7877_REG_TEMP1HIGH 10 | ||
65 | #define AD7877_REG_TEMP1LOW 11 | ||
66 | #define AD7877_REG_SEQ0 12 | ||
67 | #define AD7877_REG_SEQ1 13 | ||
68 | #define AD7877_REG_DAC 14 | ||
69 | #define AD7877_REG_NONE1 15 | ||
70 | #define AD7877_REG_EXTWRITE 15 | ||
71 | #define AD7877_REG_XPLUS 16 | ||
72 | #define AD7877_REG_YPLUS 17 | ||
73 | #define AD7877_REG_Z2 18 | ||
74 | #define AD7877_REG_aux1 19 | ||
75 | #define AD7877_REG_aux2 20 | ||
76 | #define AD7877_REG_aux3 21 | ||
77 | #define AD7877_REG_bat1 22 | ||
78 | #define AD7877_REG_bat2 23 | ||
79 | #define AD7877_REG_temp1 24 | ||
80 | #define AD7877_REG_temp2 25 | ||
81 | #define AD7877_REG_Z1 26 | ||
82 | #define AD7877_REG_GPIOCTRL1 27 | ||
83 | #define AD7877_REG_GPIOCTRL2 28 | ||
84 | #define AD7877_REG_GPIODATA 29 | ||
85 | #define AD7877_REG_NONE2 30 | ||
86 | #define AD7877_REG_NONE3 31 | ||
87 | |||
88 | #define AD7877_SEQ_YPLUS_BIT (1<<11) | ||
89 | #define AD7877_SEQ_XPLUS_BIT (1<<10) | ||
90 | #define AD7877_SEQ_Z2_BIT (1<<9) | ||
91 | #define AD7877_SEQ_AUX1_BIT (1<<8) | ||
92 | #define AD7877_SEQ_AUX2_BIT (1<<7) | ||
93 | #define AD7877_SEQ_AUX3_BIT (1<<6) | ||
94 | #define AD7877_SEQ_BAT1_BIT (1<<5) | ||
95 | #define AD7877_SEQ_BAT2_BIT (1<<4) | ||
96 | #define AD7877_SEQ_TEMP1_BIT (1<<3) | ||
97 | #define AD7877_SEQ_TEMP2_BIT (1<<2) | ||
98 | #define AD7877_SEQ_Z1_BIT (1<<1) | ||
99 | |||
100 | enum { | ||
101 | AD7877_SEQ_YPOS = 0, | ||
102 | AD7877_SEQ_XPOS = 1, | ||
103 | AD7877_SEQ_Z2 = 2, | ||
104 | AD7877_SEQ_AUX1 = 3, | ||
105 | AD7877_SEQ_AUX2 = 4, | ||
106 | AD7877_SEQ_AUX3 = 5, | ||
107 | AD7877_SEQ_BAT1 = 6, | ||
108 | AD7877_SEQ_BAT2 = 7, | ||
109 | AD7877_SEQ_TEMP1 = 8, | ||
110 | AD7877_SEQ_TEMP2 = 9, | ||
111 | AD7877_SEQ_Z1 = 10, | ||
112 | AD7877_NR_SENSE = 11, | ||
113 | }; | ||
114 | |||
115 | /* DAC Register Default RANGE 0 to Vcc, Volatge Mode, DAC On */ | ||
116 | #define AD7877_DAC_CONF 0x1 | ||
117 | |||
118 | /* If gpio3 is set AUX3/GPIO3 acts as GPIO Output */ | ||
119 | #define AD7877_EXTW_GPIO_3_CONF 0x1C4 | ||
120 | #define AD7877_EXTW_GPIO_DATA 0x200 | ||
121 | |||
122 | /* Control REG 2 */ | ||
123 | #define AD7877_TMR(x) ((x & 0x3) << 0) | ||
124 | #define AD7877_REF(x) ((x & 0x1) << 2) | ||
125 | #define AD7877_POL(x) ((x & 0x1) << 3) | ||
126 | #define AD7877_FCD(x) ((x & 0x3) << 4) | ||
127 | #define AD7877_PM(x) ((x & 0x3) << 6) | ||
128 | #define AD7877_ACQ(x) ((x & 0x3) << 8) | ||
129 | #define AD7877_AVG(x) ((x & 0x3) << 10) | ||
130 | |||
131 | /* Control REG 1 */ | ||
132 | #define AD7877_SER (1 << 11) /* non-differential */ | ||
133 | #define AD7877_DFR (0 << 11) /* differential */ | ||
134 | |||
135 | #define AD7877_MODE_NOC (0) /* Do not convert */ | ||
136 | #define AD7877_MODE_SCC (1) /* Single channel conversion */ | ||
137 | #define AD7877_MODE_SEQ0 (2) /* Sequence 0 in Slave Mode */ | ||
138 | #define AD7877_MODE_SEQ1 (3) /* Sequence 1 in Master Mode */ | ||
139 | |||
140 | #define AD7877_CHANADD(x) ((x&0xF)<<7) | ||
141 | #define AD7877_READADD(x) ((x)<<2) | ||
142 | #define AD7877_WRITEADD(x) ((x)<<12) | ||
143 | |||
144 | #define AD7877_READ_CHAN(x) (AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_SER | \ | ||
145 | AD7877_MODE_SCC | AD7877_CHANADD(AD7877_REG_ ## x) | \ | ||
146 | AD7877_READADD(AD7877_REG_ ## x)) | ||
147 | |||
148 | #define AD7877_MM_SEQUENCE (AD7877_SEQ_YPLUS_BIT | AD7877_SEQ_XPLUS_BIT | \ | ||
149 | AD7877_SEQ_Z2_BIT | AD7877_SEQ_Z1_BIT) | ||
150 | |||
151 | /* | ||
152 | * Non-touchscreen sensors only use single-ended conversions. | ||
153 | */ | ||
154 | |||
155 | struct ser_req { | ||
156 | u16 reset; | ||
157 | u16 ref_on; | ||
158 | u16 command; | ||
159 | u16 sample; | ||
160 | struct spi_message msg; | ||
161 | struct spi_transfer xfer[6]; | ||
162 | }; | ||
163 | |||
164 | struct ad7877 { | ||
165 | struct input_dev *input; | ||
166 | char phys[32]; | ||
167 | |||
168 | struct spi_device *spi; | ||
169 | u16 model; | ||
170 | u16 vref_delay_usecs; | ||
171 | u16 x_plate_ohms; | ||
172 | u16 pressure_max; | ||
173 | |||
174 | u16 cmd_crtl1; | ||
175 | u16 cmd_crtl2; | ||
176 | u16 cmd_dummy; | ||
177 | u16 dac; | ||
178 | |||
179 | u8 stopacq_polarity; | ||
180 | u8 first_conversion_delay; | ||
181 | u8 acquisition_time; | ||
182 | u8 averaging; | ||
183 | u8 pen_down_acc_interval; | ||
184 | |||
185 | u16 conversion_data[AD7877_NR_SENSE]; | ||
186 | |||
187 | struct spi_transfer xfer[AD7877_NR_SENSE + 2]; | ||
188 | struct spi_message msg; | ||
189 | |||
190 | struct mutex mutex; | ||
191 | unsigned disabled:1; /* P: mutex */ | ||
192 | unsigned gpio3:1; /* P: mutex */ | ||
193 | unsigned gpio4:1; /* P: mutex */ | ||
194 | |||
195 | spinlock_t lock; | ||
196 | struct timer_list timer; /* P: lock */ | ||
197 | unsigned pending:1; /* P: lock */ | ||
198 | }; | ||
199 | |||
200 | static int gpio3; | ||
201 | module_param(gpio3, int, 0); | ||
202 | MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3"); | ||
203 | |||
204 | /* | ||
205 | * ad7877_read/write are only used for initial setup and for sysfs controls. | ||
206 | * The main traffic is done using spi_async() in the interrupt handler. | ||
207 | */ | ||
208 | |||
209 | static int ad7877_read(struct spi_device *spi, u16 reg) | ||
210 | { | ||
211 | struct ser_req *req; | ||
212 | int status, ret; | ||
213 | |||
214 | req = kzalloc(sizeof *req, GFP_KERNEL); | ||
215 | if (!req) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | spi_message_init(&req->msg); | ||
219 | |||
220 | req->command = (u16) (AD7877_WRITEADD(AD7877_REG_CTRL1) | | ||
221 | AD7877_READADD(reg)); | ||
222 | req->xfer[0].tx_buf = &req->command; | ||
223 | req->xfer[0].len = 2; | ||
224 | |||
225 | req->xfer[1].rx_buf = &req->sample; | ||
226 | req->xfer[1].len = 2; | ||
227 | |||
228 | spi_message_add_tail(&req->xfer[0], &req->msg); | ||
229 | spi_message_add_tail(&req->xfer[1], &req->msg); | ||
230 | |||
231 | status = spi_sync(spi, &req->msg); | ||
232 | ret = status ? : req->sample; | ||
233 | |||
234 | kfree(req); | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int ad7877_write(struct spi_device *spi, u16 reg, u16 val) | ||
240 | { | ||
241 | struct ser_req *req; | ||
242 | int status; | ||
243 | |||
244 | req = kzalloc(sizeof *req, GFP_KERNEL); | ||
245 | if (!req) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | spi_message_init(&req->msg); | ||
249 | |||
250 | req->command = (u16) (AD7877_WRITEADD(reg) | (val & MAX_12BIT)); | ||
251 | req->xfer[0].tx_buf = &req->command; | ||
252 | req->xfer[0].len = 2; | ||
253 | |||
254 | spi_message_add_tail(&req->xfer[0], &req->msg); | ||
255 | |||
256 | status = spi_sync(spi, &req->msg); | ||
257 | |||
258 | kfree(req); | ||
259 | |||
260 | return status; | ||
261 | } | ||
262 | |||
263 | static int ad7877_read_adc(struct spi_device *spi, unsigned command) | ||
264 | { | ||
265 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | ||
266 | struct ser_req *req; | ||
267 | int status; | ||
268 | int sample; | ||
269 | int i; | ||
270 | |||
271 | req = kzalloc(sizeof *req, GFP_KERNEL); | ||
272 | if (!req) | ||
273 | return -ENOMEM; | ||
274 | |||
275 | spi_message_init(&req->msg); | ||
276 | |||
277 | /* activate reference, so it has time to settle; */ | ||
278 | req->ref_on = AD7877_WRITEADD(AD7877_REG_CTRL2) | | ||
279 | AD7877_POL(ts->stopacq_polarity) | | ||
280 | AD7877_AVG(0) | AD7877_PM(2) | AD7877_TMR(0) | | ||
281 | AD7877_ACQ(ts->acquisition_time) | AD7877_FCD(0); | ||
282 | |||
283 | req->reset = AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_MODE_NOC; | ||
284 | |||
285 | req->command = (u16) command; | ||
286 | |||
287 | req->xfer[0].tx_buf = &req->reset; | ||
288 | req->xfer[0].len = 2; | ||
289 | |||
290 | req->xfer[1].tx_buf = &req->ref_on; | ||
291 | req->xfer[1].len = 2; | ||
292 | req->xfer[1].delay_usecs = ts->vref_delay_usecs; | ||
293 | |||
294 | req->xfer[2].tx_buf = &req->command; | ||
295 | req->xfer[2].len = 2; | ||
296 | req->xfer[2].delay_usecs = ts->vref_delay_usecs; | ||
297 | |||
298 | req->xfer[3].rx_buf = &req->sample; | ||
299 | req->xfer[3].len = 2; | ||
300 | |||
301 | req->xfer[4].tx_buf = &ts->cmd_crtl2; /*REF OFF*/ | ||
302 | req->xfer[4].len = 2; | ||
303 | |||
304 | req->xfer[5].tx_buf = &ts->cmd_crtl1; /*DEFAULT*/ | ||
305 | req->xfer[5].len = 2; | ||
306 | |||
307 | /* group all the transfers together, so we can't interfere with | ||
308 | * reading touchscreen state; disable penirq while sampling | ||
309 | */ | ||
310 | for (i = 0; i < 6; i++) | ||
311 | spi_message_add_tail(&req->xfer[i], &req->msg); | ||
312 | |||
313 | status = spi_sync(spi, &req->msg); | ||
314 | sample = req->sample; | ||
315 | |||
316 | kfree(req); | ||
317 | |||
318 | return status ? : sample; | ||
319 | } | ||
320 | |||
321 | static void ad7877_rx(struct ad7877 *ts) | ||
322 | { | ||
323 | struct input_dev *input_dev = ts->input; | ||
324 | unsigned Rt; | ||
325 | u16 x, y, z1, z2; | ||
326 | |||
327 | x = ts->conversion_data[AD7877_SEQ_XPOS] & MAX_12BIT; | ||
328 | y = ts->conversion_data[AD7877_SEQ_YPOS] & MAX_12BIT; | ||
329 | z1 = ts->conversion_data[AD7877_SEQ_Z1] & MAX_12BIT; | ||
330 | z2 = ts->conversion_data[AD7877_SEQ_Z2] & MAX_12BIT; | ||
331 | |||
332 | /* | ||
333 | * The samples processed here are already preprocessed by the AD7877. | ||
334 | * The preprocessing function consists of an averaging filter. | ||
335 | * The combination of 'first conversion delay' and averaging provides a robust solution, | ||
336 | * discarding the spurious noise in the signal and keeping only the data of interest. | ||
337 | * The size of the averaging filter is programmable. (dev.platform_data, see linux/spi/ad7877.h) | ||
338 | * Other user-programmable conversion controls include variable acquisition time, | ||
339 | * and first conversion delay. Up to 16 averages can be taken per conversion. | ||
340 | */ | ||
341 | |||
342 | if (likely(x && z1)) { | ||
343 | /* compute touch pressure resistance using equation #1 */ | ||
344 | Rt = (z2 - z1) * x * ts->x_plate_ohms; | ||
345 | Rt /= z1; | ||
346 | Rt = (Rt + 2047) >> 12; | ||
347 | |||
348 | input_report_abs(input_dev, ABS_X, x); | ||
349 | input_report_abs(input_dev, ABS_Y, y); | ||
350 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
351 | input_sync(input_dev); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static inline void ad7877_ts_event_release(struct ad7877 *ts) | ||
356 | { | ||
357 | struct input_dev *input_dev = ts->input; | ||
358 | |||
359 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
360 | input_sync(input_dev); | ||
361 | } | ||
362 | |||
363 | static void ad7877_timer(unsigned long handle) | ||
364 | { | ||
365 | struct ad7877 *ts = (void *)handle; | ||
366 | |||
367 | ad7877_ts_event_release(ts); | ||
368 | } | ||
369 | |||
370 | static irqreturn_t ad7877_irq(int irq, void *handle) | ||
371 | { | ||
372 | struct ad7877 *ts = handle; | ||
373 | unsigned long flags; | ||
374 | int status; | ||
375 | |||
376 | /* | ||
377 | * The repeated conversion sequencer controlled by TMR kicked off | ||
378 | * too fast. We ignore the last and process the sample sequence | ||
379 | * currently in the queue. It can't be older than 9.4ms, and we | ||
380 | * need to avoid that ts->msg doesn't get issued twice while in work. | ||
381 | */ | ||
382 | |||
383 | spin_lock_irqsave(&ts->lock, flags); | ||
384 | if (!ts->pending) { | ||
385 | ts->pending = 1; | ||
386 | |||
387 | status = spi_async(ts->spi, &ts->msg); | ||
388 | if (status) | ||
389 | dev_err(&ts->spi->dev, "spi_sync --> %d\n", status); | ||
390 | } | ||
391 | spin_unlock_irqrestore(&ts->lock, flags); | ||
392 | |||
393 | return IRQ_HANDLED; | ||
394 | } | ||
395 | |||
396 | static void ad7877_callback(void *_ts) | ||
397 | { | ||
398 | struct ad7877 *ts = _ts; | ||
399 | |||
400 | spin_lock_irq(&ts->lock); | ||
401 | |||
402 | ad7877_rx(ts); | ||
403 | ts->pending = 0; | ||
404 | mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT); | ||
405 | |||
406 | spin_unlock_irq(&ts->lock); | ||
407 | } | ||
408 | |||
409 | static void ad7877_disable(struct ad7877 *ts) | ||
410 | { | ||
411 | mutex_lock(&ts->mutex); | ||
412 | |||
413 | if (!ts->disabled) { | ||
414 | ts->disabled = 1; | ||
415 | disable_irq(ts->spi->irq); | ||
416 | |||
417 | /* Wait for spi_async callback */ | ||
418 | while (ts->pending) | ||
419 | msleep(1); | ||
420 | |||
421 | if (del_timer_sync(&ts->timer)) | ||
422 | ad7877_ts_event_release(ts); | ||
423 | } | ||
424 | |||
425 | /* we know the chip's in lowpower mode since we always | ||
426 | * leave it that way after every request | ||
427 | */ | ||
428 | |||
429 | mutex_unlock(&ts->mutex); | ||
430 | } | ||
431 | |||
432 | static void ad7877_enable(struct ad7877 *ts) | ||
433 | { | ||
434 | mutex_lock(&ts->mutex); | ||
435 | |||
436 | if (ts->disabled) { | ||
437 | ts->disabled = 0; | ||
438 | enable_irq(ts->spi->irq); | ||
439 | } | ||
440 | |||
441 | mutex_unlock(&ts->mutex); | ||
442 | } | ||
443 | |||
444 | #define SHOW(name) static ssize_t \ | ||
445 | name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
446 | { \ | ||
447 | struct ad7877 *ts = dev_get_drvdata(dev); \ | ||
448 | ssize_t v = ad7877_read_adc(ts->spi, \ | ||
449 | AD7877_READ_CHAN(name)); \ | ||
450 | if (v < 0) \ | ||
451 | return v; \ | ||
452 | return sprintf(buf, "%u\n", (unsigned) v); \ | ||
453 | } \ | ||
454 | static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); | ||
455 | |||
456 | SHOW(aux1) | ||
457 | SHOW(aux2) | ||
458 | SHOW(aux3) | ||
459 | SHOW(bat1) | ||
460 | SHOW(bat2) | ||
461 | SHOW(temp1) | ||
462 | SHOW(temp2) | ||
463 | |||
464 | static ssize_t ad7877_disable_show(struct device *dev, | ||
465 | struct device_attribute *attr, char *buf) | ||
466 | { | ||
467 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
468 | |||
469 | return sprintf(buf, "%u\n", ts->disabled); | ||
470 | } | ||
471 | |||
472 | static ssize_t ad7877_disable_store(struct device *dev, | ||
473 | struct device_attribute *attr, | ||
474 | const char *buf, size_t count) | ||
475 | { | ||
476 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
477 | unsigned long val; | ||
478 | int error; | ||
479 | |||
480 | error = strict_strtoul(buf, 10, &val); | ||
481 | if (error) | ||
482 | return error; | ||
483 | |||
484 | if (val) | ||
485 | ad7877_disable(ts); | ||
486 | else | ||
487 | ad7877_enable(ts); | ||
488 | |||
489 | return count; | ||
490 | } | ||
491 | |||
492 | static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store); | ||
493 | |||
494 | static ssize_t ad7877_dac_show(struct device *dev, | ||
495 | struct device_attribute *attr, char *buf) | ||
496 | { | ||
497 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
498 | |||
499 | return sprintf(buf, "%u\n", ts->dac); | ||
500 | } | ||
501 | |||
502 | static ssize_t ad7877_dac_store(struct device *dev, | ||
503 | struct device_attribute *attr, | ||
504 | const char *buf, size_t count) | ||
505 | { | ||
506 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
507 | unsigned long val; | ||
508 | int error; | ||
509 | |||
510 | error = strict_strtoul(buf, 10, &val); | ||
511 | if (error) | ||
512 | return error; | ||
513 | |||
514 | mutex_lock(&ts->mutex); | ||
515 | ts->dac = val & 0xFF; | ||
516 | ad7877_write(ts->spi, AD7877_REG_DAC, (ts->dac << 4) | AD7877_DAC_CONF); | ||
517 | mutex_unlock(&ts->mutex); | ||
518 | |||
519 | return count; | ||
520 | } | ||
521 | |||
522 | static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store); | ||
523 | |||
524 | static ssize_t ad7877_gpio3_show(struct device *dev, | ||
525 | struct device_attribute *attr, char *buf) | ||
526 | { | ||
527 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
528 | |||
529 | return sprintf(buf, "%u\n", ts->gpio3); | ||
530 | } | ||
531 | |||
532 | static ssize_t ad7877_gpio3_store(struct device *dev, | ||
533 | struct device_attribute *attr, | ||
534 | const char *buf, size_t count) | ||
535 | { | ||
536 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
537 | unsigned long val; | ||
538 | int error; | ||
539 | |||
540 | error = strict_strtoul(buf, 10, &val); | ||
541 | if (error) | ||
542 | return error; | ||
543 | |||
544 | mutex_lock(&ts->mutex); | ||
545 | ts->gpio3 = !!val; | ||
546 | ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA | | ||
547 | (ts->gpio4 << 4) | (ts->gpio3 << 5)); | ||
548 | mutex_unlock(&ts->mutex); | ||
549 | |||
550 | return count; | ||
551 | } | ||
552 | |||
553 | static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store); | ||
554 | |||
555 | static ssize_t ad7877_gpio4_show(struct device *dev, | ||
556 | struct device_attribute *attr, char *buf) | ||
557 | { | ||
558 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
559 | |||
560 | return sprintf(buf, "%u\n", ts->gpio4); | ||
561 | } | ||
562 | |||
563 | static ssize_t ad7877_gpio4_store(struct device *dev, | ||
564 | struct device_attribute *attr, | ||
565 | const char *buf, size_t count) | ||
566 | { | ||
567 | struct ad7877 *ts = dev_get_drvdata(dev); | ||
568 | unsigned long val; | ||
569 | int error; | ||
570 | |||
571 | error = strict_strtoul(buf, 10, &val); | ||
572 | if (error) | ||
573 | return error; | ||
574 | |||
575 | mutex_lock(&ts->mutex); | ||
576 | ts->gpio4 = !!val; | ||
577 | ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA | | ||
578 | (ts->gpio4 << 4) | (ts->gpio3 << 5)); | ||
579 | mutex_unlock(&ts->mutex); | ||
580 | |||
581 | return count; | ||
582 | } | ||
583 | |||
584 | static DEVICE_ATTR(gpio4, 0664, ad7877_gpio4_show, ad7877_gpio4_store); | ||
585 | |||
586 | static struct attribute *ad7877_attributes[] = { | ||
587 | &dev_attr_temp1.attr, | ||
588 | &dev_attr_temp2.attr, | ||
589 | &dev_attr_aux1.attr, | ||
590 | &dev_attr_aux2.attr, | ||
591 | &dev_attr_bat1.attr, | ||
592 | &dev_attr_bat2.attr, | ||
593 | &dev_attr_disable.attr, | ||
594 | &dev_attr_dac.attr, | ||
595 | &dev_attr_gpio4.attr, | ||
596 | NULL | ||
597 | }; | ||
598 | |||
599 | static const struct attribute_group ad7877_attr_group = { | ||
600 | .attrs = ad7877_attributes, | ||
601 | }; | ||
602 | |||
603 | static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) | ||
604 | { | ||
605 | struct spi_message *m; | ||
606 | int i; | ||
607 | |||
608 | ts->cmd_crtl2 = AD7877_WRITEADD(AD7877_REG_CTRL2) | | ||
609 | AD7877_POL(ts->stopacq_polarity) | | ||
610 | AD7877_AVG(ts->averaging) | AD7877_PM(1) | | ||
611 | AD7877_TMR(ts->pen_down_acc_interval) | | ||
612 | AD7877_ACQ(ts->acquisition_time) | | ||
613 | AD7877_FCD(ts->first_conversion_delay); | ||
614 | |||
615 | ad7877_write(spi, AD7877_REG_CTRL2, ts->cmd_crtl2); | ||
616 | |||
617 | ts->cmd_crtl1 = AD7877_WRITEADD(AD7877_REG_CTRL1) | | ||
618 | AD7877_READADD(AD7877_REG_XPLUS-1) | | ||
619 | AD7877_MODE_SEQ1 | AD7877_DFR; | ||
620 | |||
621 | ad7877_write(spi, AD7877_REG_CTRL1, ts->cmd_crtl1); | ||
622 | |||
623 | ts->cmd_dummy = 0; | ||
624 | |||
625 | m = &ts->msg; | ||
626 | |||
627 | spi_message_init(m); | ||
628 | |||
629 | m->complete = ad7877_callback; | ||
630 | m->context = ts; | ||
631 | |||
632 | ts->xfer[0].tx_buf = &ts->cmd_crtl1; | ||
633 | ts->xfer[0].len = 2; | ||
634 | |||
635 | spi_message_add_tail(&ts->xfer[0], m); | ||
636 | |||
637 | ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */ | ||
638 | ts->xfer[1].len = 2; | ||
639 | |||
640 | spi_message_add_tail(&ts->xfer[1], m); | ||
641 | |||
642 | for (i = 0; i < 11; i++) { | ||
643 | ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i]; | ||
644 | ts->xfer[i + 2].len = 2; | ||
645 | spi_message_add_tail(&ts->xfer[i + 2], m); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | static int __devinit ad7877_probe(struct spi_device *spi) | ||
650 | { | ||
651 | struct ad7877 *ts; | ||
652 | struct input_dev *input_dev; | ||
653 | struct ad7877_platform_data *pdata = spi->dev.platform_data; | ||
654 | int err; | ||
655 | u16 verify; | ||
656 | |||
657 | if (!spi->irq) { | ||
658 | dev_dbg(&spi->dev, "no IRQ?\n"); | ||
659 | return -ENODEV; | ||
660 | } | ||
661 | |||
662 | if (!pdata) { | ||
663 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
664 | return -ENODEV; | ||
665 | } | ||
666 | |||
667 | /* don't exceed max specified SPI CLK frequency */ | ||
668 | if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { | ||
669 | dev_dbg(&spi->dev, "SPI CLK %d Hz?\n",spi->max_speed_hz); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL); | ||
674 | input_dev = input_allocate_device(); | ||
675 | if (!ts || !input_dev) { | ||
676 | err = -ENOMEM; | ||
677 | goto err_free_mem; | ||
678 | } | ||
679 | |||
680 | dev_set_drvdata(&spi->dev, ts); | ||
681 | ts->spi = spi; | ||
682 | ts->input = input_dev; | ||
683 | |||
684 | setup_timer(&ts->timer, ad7877_timer, (unsigned long) ts); | ||
685 | mutex_init(&ts->mutex); | ||
686 | spin_lock_init(&ts->lock); | ||
687 | |||
688 | ts->model = pdata->model ? : 7877; | ||
689 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | ||
690 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | ||
691 | ts->pressure_max = pdata->pressure_max ? : ~0; | ||
692 | |||
693 | ts->stopacq_polarity = pdata->stopacq_polarity; | ||
694 | ts->first_conversion_delay = pdata->first_conversion_delay; | ||
695 | ts->acquisition_time = pdata->acquisition_time; | ||
696 | ts->averaging = pdata->averaging; | ||
697 | ts->pen_down_acc_interval = pdata->pen_down_acc_interval; | ||
698 | |||
699 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); | ||
700 | |||
701 | input_dev->name = "AD7877 Touchscreen"; | ||
702 | input_dev->phys = ts->phys; | ||
703 | input_dev->dev.parent = &spi->dev; | ||
704 | |||
705 | __set_bit(EV_ABS, input_dev->evbit); | ||
706 | __set_bit(ABS_X, input_dev->absbit); | ||
707 | __set_bit(ABS_Y, input_dev->absbit); | ||
708 | __set_bit(ABS_PRESSURE, input_dev->absbit); | ||
709 | |||
710 | input_set_abs_params(input_dev, ABS_X, | ||
711 | pdata->x_min ? : 0, | ||
712 | pdata->x_max ? : MAX_12BIT, | ||
713 | 0, 0); | ||
714 | input_set_abs_params(input_dev, ABS_Y, | ||
715 | pdata->y_min ? : 0, | ||
716 | pdata->y_max ? : MAX_12BIT, | ||
717 | 0, 0); | ||
718 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
719 | pdata->pressure_min, pdata->pressure_max, 0, 0); | ||
720 | |||
721 | ad7877_write(spi, AD7877_REG_SEQ1, AD7877_MM_SEQUENCE); | ||
722 | |||
723 | verify = ad7877_read(spi, AD7877_REG_SEQ1); | ||
724 | |||
725 | if (verify != AD7877_MM_SEQUENCE){ | ||
726 | dev_err(&spi->dev, "%s: Failed to probe %s\n", | ||
727 | dev_name(&spi->dev), input_dev->name); | ||
728 | err = -ENODEV; | ||
729 | goto err_free_mem; | ||
730 | } | ||
731 | |||
732 | if (gpio3) | ||
733 | ad7877_write(spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_3_CONF); | ||
734 | |||
735 | ad7877_setup_ts_def_msg(spi, ts); | ||
736 | |||
737 | /* Request AD7877 /DAV GPIO interrupt */ | ||
738 | |||
739 | err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING | | ||
740 | IRQF_SAMPLE_RANDOM, spi->dev.driver->name, ts); | ||
741 | if (err) { | ||
742 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | ||
743 | goto err_free_mem; | ||
744 | } | ||
745 | |||
746 | err = sysfs_create_group(&spi->dev.kobj, &ad7877_attr_group); | ||
747 | if (err) | ||
748 | goto err_free_irq; | ||
749 | |||
750 | err = device_create_file(&spi->dev, | ||
751 | gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); | ||
752 | if (err) | ||
753 | goto err_remove_attr_group; | ||
754 | |||
755 | err = input_register_device(input_dev); | ||
756 | if (err) | ||
757 | goto err_remove_attr; | ||
758 | |||
759 | return 0; | ||
760 | |||
761 | err_remove_attr: | ||
762 | device_remove_file(&spi->dev, | ||
763 | gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); | ||
764 | err_remove_attr_group: | ||
765 | sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); | ||
766 | err_free_irq: | ||
767 | free_irq(spi->irq, ts); | ||
768 | err_free_mem: | ||
769 | input_free_device(input_dev); | ||
770 | kfree(ts); | ||
771 | dev_set_drvdata(&spi->dev, NULL); | ||
772 | return err; | ||
773 | } | ||
774 | |||
775 | static int __devexit ad7877_remove(struct spi_device *spi) | ||
776 | { | ||
777 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | ||
778 | |||
779 | sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); | ||
780 | device_remove_file(&spi->dev, | ||
781 | gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); | ||
782 | |||
783 | ad7877_disable(ts); | ||
784 | free_irq(ts->spi->irq, ts); | ||
785 | |||
786 | input_unregister_device(ts->input); | ||
787 | kfree(ts); | ||
788 | |||
789 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | ||
790 | dev_set_drvdata(&spi->dev, NULL); | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | #ifdef CONFIG_PM | ||
796 | static int ad7877_suspend(struct spi_device *spi, pm_message_t message) | ||
797 | { | ||
798 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | ||
799 | |||
800 | ad7877_disable(ts); | ||
801 | |||
802 | return 0; | ||
803 | } | ||
804 | |||
805 | static int ad7877_resume(struct spi_device *spi) | ||
806 | { | ||
807 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | ||
808 | |||
809 | ad7877_enable(ts); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | #else | ||
814 | #define ad7877_suspend NULL | ||
815 | #define ad7877_resume NULL | ||
816 | #endif | ||
817 | |||
818 | static struct spi_driver ad7877_driver = { | ||
819 | .driver = { | ||
820 | .name = "ad7877", | ||
821 | .bus = &spi_bus_type, | ||
822 | .owner = THIS_MODULE, | ||
823 | }, | ||
824 | .probe = ad7877_probe, | ||
825 | .remove = __devexit_p(ad7877_remove), | ||
826 | .suspend = ad7877_suspend, | ||
827 | .resume = ad7877_resume, | ||
828 | }; | ||
829 | |||
830 | static int __init ad7877_init(void) | ||
831 | { | ||
832 | return spi_register_driver(&ad7877_driver); | ||
833 | } | ||
834 | module_init(ad7877_init); | ||
835 | |||
836 | static void __exit ad7877_exit(void) | ||
837 | { | ||
838 | spi_unregister_driver(&ad7877_driver); | ||
839 | } | ||
840 | module_exit(ad7877_exit); | ||
841 | |||
842 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
843 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); | ||
844 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c new file mode 100644 index 000000000000..ea4c61d68683 --- /dev/null +++ b/drivers/input/touchscreen/ad7879.c | |||
@@ -0,0 +1,782 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Michael Hennerich, Analog Devices Inc. | ||
3 | * | ||
4 | * Description: AD7879 based touchscreen, and GPIO driver (I2C/SPI Interface) | ||
5 | * | ||
6 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, see the file COPYING, or write | ||
20 | * to the Free Software Foundation, Inc., | ||
21 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * | ||
23 | * History: | ||
24 | * Copyright (c) 2005 David Brownell | ||
25 | * Copyright (c) 2006 Nokia Corporation | ||
26 | * Various changes: Imre Deak <imre.deak@nokia.com> | ||
27 | * | ||
28 | * Using code from: | ||
29 | * - corgi_ts.c | ||
30 | * Copyright (C) 2004-2005 Richard Purdie | ||
31 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
32 | * Copyright (C) 2002 MontaVista Software | ||
33 | * Copyright (C) 2004 Texas Instruments | ||
34 | * Copyright (C) 2005 Dirk Behme | ||
35 | * - ad7877.c | ||
36 | * Copyright (C) 2006-2008 Analog Devices Inc. | ||
37 | */ | ||
38 | |||
39 | #include <linux/device.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/input.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <linux/irq.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <linux/workqueue.h> | ||
47 | #include <linux/spi/spi.h> | ||
48 | #include <linux/i2c.h> | ||
49 | |||
50 | #include <linux/spi/ad7879.h> | ||
51 | |||
52 | #define AD7879_REG_ZEROS 0 | ||
53 | #define AD7879_REG_CTRL1 1 | ||
54 | #define AD7879_REG_CTRL2 2 | ||
55 | #define AD7879_REG_CTRL3 3 | ||
56 | #define AD7879_REG_AUX1HIGH 4 | ||
57 | #define AD7879_REG_AUX1LOW 5 | ||
58 | #define AD7879_REG_TEMP1HIGH 6 | ||
59 | #define AD7879_REG_TEMP1LOW 7 | ||
60 | #define AD7879_REG_XPLUS 8 | ||
61 | #define AD7879_REG_YPLUS 9 | ||
62 | #define AD7879_REG_Z1 10 | ||
63 | #define AD7879_REG_Z2 11 | ||
64 | #define AD7879_REG_AUXVBAT 12 | ||
65 | #define AD7879_REG_TEMP 13 | ||
66 | #define AD7879_REG_REVID 14 | ||
67 | |||
68 | /* Control REG 1 */ | ||
69 | #define AD7879_TMR(x) ((x & 0xFF) << 0) | ||
70 | #define AD7879_ACQ(x) ((x & 0x3) << 8) | ||
71 | #define AD7879_MODE_NOC (0 << 10) /* Do not convert */ | ||
72 | #define AD7879_MODE_SCC (1 << 10) /* Single channel conversion */ | ||
73 | #define AD7879_MODE_SEQ0 (2 << 10) /* Sequence 0 in Slave Mode */ | ||
74 | #define AD7879_MODE_SEQ1 (3 << 10) /* Sequence 1 in Master Mode */ | ||
75 | #define AD7879_MODE_INT (1 << 15) /* PENIRQ disabled INT enabled */ | ||
76 | |||
77 | /* Control REG 2 */ | ||
78 | #define AD7879_FCD(x) ((x & 0x3) << 0) | ||
79 | #define AD7879_RESET (1 << 4) | ||
80 | #define AD7879_MFS(x) ((x & 0x3) << 5) | ||
81 | #define AD7879_AVG(x) ((x & 0x3) << 7) | ||
82 | #define AD7879_SER (1 << 9) /* non-differential */ | ||
83 | #define AD7879_DFR (0 << 9) /* differential */ | ||
84 | #define AD7879_GPIOPOL (1 << 10) | ||
85 | #define AD7879_GPIODIR (1 << 11) | ||
86 | #define AD7879_GPIO_DATA (1 << 12) | ||
87 | #define AD7879_GPIO_EN (1 << 13) | ||
88 | #define AD7879_PM(x) ((x & 0x3) << 14) | ||
89 | #define AD7879_PM_SHUTDOWN (0) | ||
90 | #define AD7879_PM_DYN (1) | ||
91 | #define AD7879_PM_FULLON (2) | ||
92 | |||
93 | /* Control REG 3 */ | ||
94 | #define AD7879_TEMPMASK_BIT (1<<15) | ||
95 | #define AD7879_AUXVBATMASK_BIT (1<<14) | ||
96 | #define AD7879_INTMODE_BIT (1<<13) | ||
97 | #define AD7879_GPIOALERTMASK_BIT (1<<12) | ||
98 | #define AD7879_AUXLOW_BIT (1<<11) | ||
99 | #define AD7879_AUXHIGH_BIT (1<<10) | ||
100 | #define AD7879_TEMPLOW_BIT (1<<9) | ||
101 | #define AD7879_TEMPHIGH_BIT (1<<8) | ||
102 | #define AD7879_YPLUS_BIT (1<<7) | ||
103 | #define AD7879_XPLUS_BIT (1<<6) | ||
104 | #define AD7879_Z1_BIT (1<<5) | ||
105 | #define AD7879_Z2_BIT (1<<4) | ||
106 | #define AD7879_AUX_BIT (1<<3) | ||
107 | #define AD7879_VBAT_BIT (1<<2) | ||
108 | #define AD7879_TEMP_BIT (1<<1) | ||
109 | |||
110 | enum { | ||
111 | AD7879_SEQ_XPOS = 0, | ||
112 | AD7879_SEQ_YPOS = 1, | ||
113 | AD7879_SEQ_Z1 = 2, | ||
114 | AD7879_SEQ_Z2 = 3, | ||
115 | AD7879_NR_SENSE = 4, | ||
116 | }; | ||
117 | |||
118 | #define MAX_12BIT ((1<<12)-1) | ||
119 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) | ||
120 | |||
121 | #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) | ||
122 | #define AD7879_DEVID 0x7A | ||
123 | typedef struct spi_device bus_device; | ||
124 | #elif defined(CONFIG_TOUCHSCREEN_AD7879_I2C) || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE) | ||
125 | #define AD7879_DEVID 0x79 | ||
126 | typedef struct i2c_client bus_device; | ||
127 | #endif | ||
128 | |||
129 | struct ad7879 { | ||
130 | bus_device *bus; | ||
131 | struct input_dev *input; | ||
132 | struct work_struct work; | ||
133 | struct timer_list timer; | ||
134 | |||
135 | struct mutex mutex; | ||
136 | unsigned disabled:1; /* P: mutex */ | ||
137 | |||
138 | #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) | ||
139 | struct spi_message msg; | ||
140 | struct spi_transfer xfer[AD7879_NR_SENSE + 1]; | ||
141 | u16 cmd; | ||
142 | #endif | ||
143 | u16 conversion_data[AD7879_NR_SENSE]; | ||
144 | char phys[32]; | ||
145 | u8 first_conversion_delay; | ||
146 | u8 acquisition_time; | ||
147 | u8 averaging; | ||
148 | u8 pen_down_acc_interval; | ||
149 | u8 median; | ||
150 | u16 x_plate_ohms; | ||
151 | u16 pressure_max; | ||
152 | u16 gpio_init; | ||
153 | u16 cmd_crtl1; | ||
154 | u16 cmd_crtl2; | ||
155 | u16 cmd_crtl3; | ||
156 | unsigned gpio:1; | ||
157 | }; | ||
158 | |||
159 | static int ad7879_read(bus_device *, u8); | ||
160 | static int ad7879_write(bus_device *, u8, u16); | ||
161 | static void ad7879_collect(struct ad7879 *); | ||
162 | |||
163 | static void ad7879_report(struct ad7879 *ts) | ||
164 | { | ||
165 | struct input_dev *input_dev = ts->input; | ||
166 | unsigned Rt; | ||
167 | u16 x, y, z1, z2; | ||
168 | |||
169 | x = ts->conversion_data[AD7879_SEQ_XPOS] & MAX_12BIT; | ||
170 | y = ts->conversion_data[AD7879_SEQ_YPOS] & MAX_12BIT; | ||
171 | z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT; | ||
172 | z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT; | ||
173 | |||
174 | /* | ||
175 | * The samples processed here are already preprocessed by the AD7879. | ||
176 | * The preprocessing function consists of a median and an averaging filter. | ||
177 | * The combination of these two techniques provides a robust solution, | ||
178 | * discarding the spurious noise in the signal and keeping only the data of interest. | ||
179 | * The size of both filters is programmable. (dev.platform_data, see linux/spi/ad7879.h) | ||
180 | * Other user-programmable conversion controls include variable acquisition time, | ||
181 | * and first conversion delay. Up to 16 averages can be taken per conversion. | ||
182 | */ | ||
183 | |||
184 | if (likely(x && z1)) { | ||
185 | /* compute touch pressure resistance using equation #1 */ | ||
186 | Rt = (z2 - z1) * x * ts->x_plate_ohms; | ||
187 | Rt /= z1; | ||
188 | Rt = (Rt + 2047) >> 12; | ||
189 | |||
190 | input_report_abs(input_dev, ABS_X, x); | ||
191 | input_report_abs(input_dev, ABS_Y, y); | ||
192 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
193 | input_sync(input_dev); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | static void ad7879_work(struct work_struct *work) | ||
198 | { | ||
199 | struct ad7879 *ts = container_of(work, struct ad7879, work); | ||
200 | |||
201 | /* use keventd context to read the result registers */ | ||
202 | ad7879_collect(ts); | ||
203 | ad7879_report(ts); | ||
204 | mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT); | ||
205 | } | ||
206 | |||
207 | static void ad7879_ts_event_release(struct ad7879 *ts) | ||
208 | { | ||
209 | struct input_dev *input_dev = ts->input; | ||
210 | |||
211 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
212 | input_sync(input_dev); | ||
213 | } | ||
214 | |||
215 | static void ad7879_timer(unsigned long handle) | ||
216 | { | ||
217 | struct ad7879 *ts = (void *)handle; | ||
218 | |||
219 | ad7879_ts_event_release(ts); | ||
220 | } | ||
221 | |||
222 | static irqreturn_t ad7879_irq(int irq, void *handle) | ||
223 | { | ||
224 | struct ad7879 *ts = handle; | ||
225 | |||
226 | /* The repeated conversion sequencer controlled by TMR kicked off too fast. | ||
227 | * We ignore the last and process the sample sequence currently in the queue. | ||
228 | * It can't be older than 9.4ms | ||
229 | */ | ||
230 | |||
231 | if (!work_pending(&ts->work)) | ||
232 | schedule_work(&ts->work); | ||
233 | |||
234 | return IRQ_HANDLED; | ||
235 | } | ||
236 | |||
237 | static void ad7879_setup(struct ad7879 *ts) | ||
238 | { | ||
239 | ts->cmd_crtl3 = AD7879_YPLUS_BIT | | ||
240 | AD7879_XPLUS_BIT | | ||
241 | AD7879_Z2_BIT | | ||
242 | AD7879_Z1_BIT | | ||
243 | AD7879_TEMPMASK_BIT | | ||
244 | AD7879_AUXVBATMASK_BIT | | ||
245 | AD7879_GPIOALERTMASK_BIT; | ||
246 | |||
247 | ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR | | ||
248 | AD7879_AVG(ts->averaging) | | ||
249 | AD7879_MFS(ts->median) | | ||
250 | AD7879_FCD(ts->first_conversion_delay) | | ||
251 | ts->gpio_init; | ||
252 | |||
253 | ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 | | ||
254 | AD7879_ACQ(ts->acquisition_time) | | ||
255 | AD7879_TMR(ts->pen_down_acc_interval); | ||
256 | |||
257 | ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); | ||
258 | ad7879_write(ts->bus, AD7879_REG_CTRL3, ts->cmd_crtl3); | ||
259 | ad7879_write(ts->bus, AD7879_REG_CTRL1, ts->cmd_crtl1); | ||
260 | } | ||
261 | |||
262 | static void ad7879_disable(struct ad7879 *ts) | ||
263 | { | ||
264 | mutex_lock(&ts->mutex); | ||
265 | |||
266 | if (!ts->disabled) { | ||
267 | |||
268 | ts->disabled = 1; | ||
269 | disable_irq(ts->bus->irq); | ||
270 | |||
271 | cancel_work_sync(&ts->work); | ||
272 | |||
273 | if (del_timer_sync(&ts->timer)) | ||
274 | ad7879_ts_event_release(ts); | ||
275 | |||
276 | ad7879_write(ts->bus, AD7879_REG_CTRL2, | ||
277 | AD7879_PM(AD7879_PM_SHUTDOWN)); | ||
278 | } | ||
279 | |||
280 | mutex_unlock(&ts->mutex); | ||
281 | } | ||
282 | |||
283 | static void ad7879_enable(struct ad7879 *ts) | ||
284 | { | ||
285 | mutex_lock(&ts->mutex); | ||
286 | |||
287 | if (ts->disabled) { | ||
288 | ad7879_setup(ts); | ||
289 | ts->disabled = 0; | ||
290 | enable_irq(ts->bus->irq); | ||
291 | } | ||
292 | |||
293 | mutex_unlock(&ts->mutex); | ||
294 | } | ||
295 | |||
296 | static ssize_t ad7879_disable_show(struct device *dev, | ||
297 | struct device_attribute *attr, char *buf) | ||
298 | { | ||
299 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
300 | |||
301 | return sprintf(buf, "%u\n", ts->disabled); | ||
302 | } | ||
303 | |||
304 | static ssize_t ad7879_disable_store(struct device *dev, | ||
305 | struct device_attribute *attr, | ||
306 | const char *buf, size_t count) | ||
307 | { | ||
308 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
309 | unsigned long val; | ||
310 | int error; | ||
311 | |||
312 | error = strict_strtoul(buf, 10, &val); | ||
313 | if (error) | ||
314 | return error; | ||
315 | |||
316 | if (val) | ||
317 | ad7879_disable(ts); | ||
318 | else | ||
319 | ad7879_enable(ts); | ||
320 | |||
321 | return count; | ||
322 | } | ||
323 | |||
324 | static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store); | ||
325 | |||
326 | static ssize_t ad7879_gpio_show(struct device *dev, | ||
327 | struct device_attribute *attr, char *buf) | ||
328 | { | ||
329 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
330 | |||
331 | return sprintf(buf, "%u\n", ts->gpio); | ||
332 | } | ||
333 | |||
334 | static ssize_t ad7879_gpio_store(struct device *dev, | ||
335 | struct device_attribute *attr, | ||
336 | const char *buf, size_t count) | ||
337 | { | ||
338 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
339 | unsigned long val; | ||
340 | int error; | ||
341 | |||
342 | error = strict_strtoul(buf, 10, &val); | ||
343 | if (error) | ||
344 | return error; | ||
345 | |||
346 | mutex_lock(&ts->mutex); | ||
347 | ts->gpio = !!val; | ||
348 | error = ad7879_write(ts->bus, AD7879_REG_CTRL2, | ||
349 | ts->gpio ? | ||
350 | ts->cmd_crtl2 & ~AD7879_GPIO_DATA : | ||
351 | ts->cmd_crtl2 | AD7879_GPIO_DATA); | ||
352 | mutex_unlock(&ts->mutex); | ||
353 | |||
354 | return error ? : count; | ||
355 | } | ||
356 | |||
357 | static DEVICE_ATTR(gpio, 0664, ad7879_gpio_show, ad7879_gpio_store); | ||
358 | |||
359 | static struct attribute *ad7879_attributes[] = { | ||
360 | &dev_attr_disable.attr, | ||
361 | &dev_attr_gpio.attr, | ||
362 | NULL | ||
363 | }; | ||
364 | |||
365 | static const struct attribute_group ad7879_attr_group = { | ||
366 | .attrs = ad7879_attributes, | ||
367 | }; | ||
368 | |||
369 | static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | ||
370 | { | ||
371 | struct input_dev *input_dev; | ||
372 | struct ad7879_platform_data *pdata = bus->dev.platform_data; | ||
373 | int err; | ||
374 | u16 revid; | ||
375 | |||
376 | if (!bus->irq) { | ||
377 | dev_err(&bus->dev, "no IRQ?\n"); | ||
378 | return -ENODEV; | ||
379 | } | ||
380 | |||
381 | if (!pdata) { | ||
382 | dev_err(&bus->dev, "no platform data?\n"); | ||
383 | return -ENODEV; | ||
384 | } | ||
385 | |||
386 | input_dev = input_allocate_device(); | ||
387 | if (!input_dev) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | ts->input = input_dev; | ||
391 | |||
392 | setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); | ||
393 | INIT_WORK(&ts->work, ad7879_work); | ||
394 | mutex_init(&ts->mutex); | ||
395 | |||
396 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | ||
397 | ts->pressure_max = pdata->pressure_max ? : ~0; | ||
398 | |||
399 | ts->first_conversion_delay = pdata->first_conversion_delay; | ||
400 | ts->acquisition_time = pdata->acquisition_time; | ||
401 | ts->averaging = pdata->averaging; | ||
402 | ts->pen_down_acc_interval = pdata->pen_down_acc_interval; | ||
403 | ts->median = pdata->median; | ||
404 | |||
405 | if (pdata->gpio_output) | ||
406 | ts->gpio_init = AD7879_GPIO_EN | | ||
407 | (pdata->gpio_default ? 0 : AD7879_GPIO_DATA); | ||
408 | else | ||
409 | ts->gpio_init = AD7879_GPIO_EN | AD7879_GPIODIR; | ||
410 | |||
411 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&bus->dev)); | ||
412 | |||
413 | input_dev->name = "AD7879 Touchscreen"; | ||
414 | input_dev->phys = ts->phys; | ||
415 | input_dev->dev.parent = &bus->dev; | ||
416 | |||
417 | __set_bit(EV_ABS, input_dev->evbit); | ||
418 | __set_bit(ABS_X, input_dev->absbit); | ||
419 | __set_bit(ABS_Y, input_dev->absbit); | ||
420 | __set_bit(ABS_PRESSURE, input_dev->absbit); | ||
421 | |||
422 | input_set_abs_params(input_dev, ABS_X, | ||
423 | pdata->x_min ? : 0, | ||
424 | pdata->x_max ? : MAX_12BIT, | ||
425 | 0, 0); | ||
426 | input_set_abs_params(input_dev, ABS_Y, | ||
427 | pdata->y_min ? : 0, | ||
428 | pdata->y_max ? : MAX_12BIT, | ||
429 | 0, 0); | ||
430 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
431 | pdata->pressure_min, pdata->pressure_max, 0, 0); | ||
432 | |||
433 | err = ad7879_write(bus, AD7879_REG_CTRL2, AD7879_RESET); | ||
434 | |||
435 | if (err < 0) { | ||
436 | dev_err(&bus->dev, "Failed to write %s\n", input_dev->name); | ||
437 | goto err_free_mem; | ||
438 | } | ||
439 | |||
440 | revid = ad7879_read(bus, AD7879_REG_REVID); | ||
441 | |||
442 | if ((revid & 0xFF) != AD7879_DEVID) { | ||
443 | dev_err(&bus->dev, "Failed to probe %s\n", input_dev->name); | ||
444 | err = -ENODEV; | ||
445 | goto err_free_mem; | ||
446 | } | ||
447 | |||
448 | ad7879_setup(ts); | ||
449 | |||
450 | err = request_irq(bus->irq, ad7879_irq, | ||
451 | IRQF_TRIGGER_FALLING | IRQF_SAMPLE_RANDOM, | ||
452 | bus->dev.driver->name, ts); | ||
453 | |||
454 | if (err) { | ||
455 | dev_err(&bus->dev, "irq %d busy?\n", bus->irq); | ||
456 | goto err_free_mem; | ||
457 | } | ||
458 | |||
459 | err = sysfs_create_group(&bus->dev.kobj, &ad7879_attr_group); | ||
460 | if (err) | ||
461 | goto err_free_irq; | ||
462 | |||
463 | err = input_register_device(input_dev); | ||
464 | if (err) | ||
465 | goto err_remove_attr; | ||
466 | |||
467 | dev_info(&bus->dev, "Rev.%d touchscreen, irq %d\n", | ||
468 | revid >> 8, bus->irq); | ||
469 | |||
470 | return 0; | ||
471 | |||
472 | err_remove_attr: | ||
473 | sysfs_remove_group(&bus->dev.kobj, &ad7879_attr_group); | ||
474 | err_free_irq: | ||
475 | free_irq(bus->irq, ts); | ||
476 | err_free_mem: | ||
477 | input_free_device(input_dev); | ||
478 | |||
479 | return err; | ||
480 | } | ||
481 | |||
482 | static int __devexit ad7879_destroy(bus_device *bus, struct ad7879 *ts) | ||
483 | { | ||
484 | ad7879_disable(ts); | ||
485 | sysfs_remove_group(&ts->bus->dev.kobj, &ad7879_attr_group); | ||
486 | free_irq(ts->bus->irq, ts); | ||
487 | input_unregister_device(ts->input); | ||
488 | dev_dbg(&bus->dev, "unregistered touchscreen\n"); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | #ifdef CONFIG_PM | ||
494 | static int ad7879_suspend(bus_device *bus, pm_message_t message) | ||
495 | { | ||
496 | struct ad7879 *ts = dev_get_drvdata(&bus->dev); | ||
497 | |||
498 | ad7879_disable(ts); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static int ad7879_resume(bus_device *bus) | ||
504 | { | ||
505 | struct ad7879 *ts = dev_get_drvdata(&bus->dev); | ||
506 | |||
507 | ad7879_enable(ts); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | #else | ||
512 | #define ad7879_suspend NULL | ||
513 | #define ad7879_resume NULL | ||
514 | #endif | ||
515 | |||
516 | #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) | ||
517 | #define MAX_SPI_FREQ_HZ 5000000 | ||
518 | #define AD7879_CMD_MAGIC 0xE000 | ||
519 | #define AD7879_CMD_READ (1 << 10) | ||
520 | #define AD7879_WRITECMD(reg) (AD7879_CMD_MAGIC | (reg & 0xF)) | ||
521 | #define AD7879_READCMD(reg) (AD7879_CMD_MAGIC | AD7879_CMD_READ | (reg & 0xF)) | ||
522 | |||
523 | struct ser_req { | ||
524 | u16 command; | ||
525 | u16 data; | ||
526 | struct spi_message msg; | ||
527 | struct spi_transfer xfer[2]; | ||
528 | }; | ||
529 | |||
530 | /* | ||
531 | * ad7879_read/write are only used for initial setup and for sysfs controls. | ||
532 | * The main traffic is done in ad7879_collect(). | ||
533 | */ | ||
534 | |||
535 | static int ad7879_read(struct spi_device *spi, u8 reg) | ||
536 | { | ||
537 | struct ser_req *req; | ||
538 | int status, ret; | ||
539 | |||
540 | req = kzalloc(sizeof *req, GFP_KERNEL); | ||
541 | if (!req) | ||
542 | return -ENOMEM; | ||
543 | |||
544 | spi_message_init(&req->msg); | ||
545 | |||
546 | req->command = (u16) AD7879_READCMD(reg); | ||
547 | req->xfer[0].tx_buf = &req->command; | ||
548 | req->xfer[0].len = 2; | ||
549 | |||
550 | req->xfer[1].rx_buf = &req->data; | ||
551 | req->xfer[1].len = 2; | ||
552 | |||
553 | spi_message_add_tail(&req->xfer[0], &req->msg); | ||
554 | spi_message_add_tail(&req->xfer[1], &req->msg); | ||
555 | |||
556 | status = spi_sync(spi, &req->msg); | ||
557 | ret = status ? : req->data; | ||
558 | |||
559 | kfree(req); | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int ad7879_write(struct spi_device *spi, u8 reg, u16 val) | ||
565 | { | ||
566 | struct ser_req *req; | ||
567 | int status; | ||
568 | |||
569 | req = kzalloc(sizeof *req, GFP_KERNEL); | ||
570 | if (!req) | ||
571 | return -ENOMEM; | ||
572 | |||
573 | spi_message_init(&req->msg); | ||
574 | |||
575 | req->command = (u16) AD7879_WRITECMD(reg); | ||
576 | req->xfer[0].tx_buf = &req->command; | ||
577 | req->xfer[0].len = 2; | ||
578 | |||
579 | req->data = val; | ||
580 | req->xfer[1].tx_buf = &req->data; | ||
581 | req->xfer[1].len = 2; | ||
582 | |||
583 | spi_message_add_tail(&req->xfer[0], &req->msg); | ||
584 | spi_message_add_tail(&req->xfer[1], &req->msg); | ||
585 | |||
586 | status = spi_sync(spi, &req->msg); | ||
587 | |||
588 | kfree(req); | ||
589 | |||
590 | return status; | ||
591 | } | ||
592 | |||
593 | static void ad7879_collect(struct ad7879 *ts) | ||
594 | { | ||
595 | int status = spi_sync(ts->bus, &ts->msg); | ||
596 | |||
597 | if (status) | ||
598 | dev_err(&ts->bus->dev, "spi_sync --> %d\n", status); | ||
599 | } | ||
600 | |||
601 | static void ad7879_setup_ts_def_msg(struct ad7879 *ts) | ||
602 | { | ||
603 | struct spi_message *m; | ||
604 | int i; | ||
605 | |||
606 | ts->cmd = (u16) AD7879_READCMD(AD7879_REG_XPLUS); | ||
607 | |||
608 | m = &ts->msg; | ||
609 | spi_message_init(m); | ||
610 | ts->xfer[0].tx_buf = &ts->cmd; | ||
611 | ts->xfer[0].len = 2; | ||
612 | |||
613 | spi_message_add_tail(&ts->xfer[0], m); | ||
614 | |||
615 | for (i = 0; i < AD7879_NR_SENSE; i++) { | ||
616 | ts->xfer[i + 1].rx_buf = &ts->conversion_data[i]; | ||
617 | ts->xfer[i + 1].len = 2; | ||
618 | spi_message_add_tail(&ts->xfer[i + 1], m); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | static int __devinit ad7879_probe(struct spi_device *spi) | ||
623 | { | ||
624 | struct ad7879 *ts; | ||
625 | int error; | ||
626 | |||
627 | /* don't exceed max specified SPI CLK frequency */ | ||
628 | if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { | ||
629 | dev_err(&spi->dev, "SPI CLK %d Hz?\n", spi->max_speed_hz); | ||
630 | return -EINVAL; | ||
631 | } | ||
632 | |||
633 | ts = kzalloc(sizeof(struct ad7879), GFP_KERNEL); | ||
634 | if (!ts) | ||
635 | return -ENOMEM; | ||
636 | |||
637 | dev_set_drvdata(&spi->dev, ts); | ||
638 | ts->bus = spi; | ||
639 | |||
640 | ad7879_setup_ts_def_msg(ts); | ||
641 | |||
642 | error = ad7879_construct(spi, ts); | ||
643 | if (error) { | ||
644 | dev_set_drvdata(&spi->dev, NULL); | ||
645 | kfree(ts); | ||
646 | } | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | static int __devexit ad7879_remove(struct spi_device *spi) | ||
652 | { | ||
653 | struct ad7879 *ts = dev_get_drvdata(&spi->dev); | ||
654 | |||
655 | ad7879_destroy(spi, ts); | ||
656 | dev_set_drvdata(&spi->dev, NULL); | ||
657 | kfree(ts); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static struct spi_driver ad7879_driver = { | ||
663 | .driver = { | ||
664 | .name = "ad7879", | ||
665 | .bus = &spi_bus_type, | ||
666 | .owner = THIS_MODULE, | ||
667 | }, | ||
668 | .probe = ad7879_probe, | ||
669 | .remove = __devexit_p(ad7879_remove), | ||
670 | .suspend = ad7879_suspend, | ||
671 | .resume = ad7879_resume, | ||
672 | }; | ||
673 | |||
674 | static int __init ad7879_init(void) | ||
675 | { | ||
676 | return spi_register_driver(&ad7879_driver); | ||
677 | } | ||
678 | module_init(ad7879_init); | ||
679 | |||
680 | static void __exit ad7879_exit(void) | ||
681 | { | ||
682 | spi_unregister_driver(&ad7879_driver); | ||
683 | } | ||
684 | module_exit(ad7879_exit); | ||
685 | |||
686 | #elif defined(CONFIG_TOUCHSCREEN_AD7879_I2C) || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE) | ||
687 | |||
688 | /* All registers are word-sized. | ||
689 | * AD7879 uses a high-byte first convention. | ||
690 | */ | ||
691 | static int ad7879_read(struct i2c_client *client, u8 reg) | ||
692 | { | ||
693 | return swab16(i2c_smbus_read_word_data(client, reg)); | ||
694 | } | ||
695 | |||
696 | static int ad7879_write(struct i2c_client *client, u8 reg, u16 val) | ||
697 | { | ||
698 | return i2c_smbus_write_word_data(client, reg, swab16(val)); | ||
699 | } | ||
700 | |||
701 | static void ad7879_collect(struct ad7879 *ts) | ||
702 | { | ||
703 | int i; | ||
704 | |||
705 | for (i = 0; i < AD7879_NR_SENSE; i++) | ||
706 | ts->conversion_data[i] = ad7879_read(ts->bus, | ||
707 | AD7879_REG_XPLUS + i); | ||
708 | } | ||
709 | |||
710 | static int __devinit ad7879_probe(struct i2c_client *client, | ||
711 | const struct i2c_device_id *id) | ||
712 | { | ||
713 | struct ad7879 *ts; | ||
714 | int error; | ||
715 | |||
716 | if (!i2c_check_functionality(client->adapter, | ||
717 | I2C_FUNC_SMBUS_WORD_DATA)) { | ||
718 | dev_err(&client->dev, "SMBUS Word Data not Supported\n"); | ||
719 | return -EIO; | ||
720 | } | ||
721 | |||
722 | ts = kzalloc(sizeof(struct ad7879), GFP_KERNEL); | ||
723 | if (!ts) | ||
724 | return -ENOMEM; | ||
725 | |||
726 | i2c_set_clientdata(client, ts); | ||
727 | ts->bus = client; | ||
728 | |||
729 | error = ad7879_construct(client, ts); | ||
730 | if (error) { | ||
731 | i2c_set_clientdata(client, NULL); | ||
732 | kfree(ts); | ||
733 | } | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int __devexit ad7879_remove(struct i2c_client *client) | ||
739 | { | ||
740 | struct ad7879 *ts = dev_get_drvdata(&client->dev); | ||
741 | |||
742 | ad7879_destroy(client, ts); | ||
743 | i2c_set_clientdata(client, NULL); | ||
744 | kfree(ts); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static const struct i2c_device_id ad7879_id[] = { | ||
750 | { "ad7879", 0 }, | ||
751 | { } | ||
752 | }; | ||
753 | MODULE_DEVICE_TABLE(i2c, ad7879_id); | ||
754 | |||
755 | static struct i2c_driver ad7879_driver = { | ||
756 | .driver = { | ||
757 | .name = "ad7879", | ||
758 | .owner = THIS_MODULE, | ||
759 | }, | ||
760 | .probe = ad7879_probe, | ||
761 | .remove = __devexit_p(ad7879_remove), | ||
762 | .suspend = ad7879_suspend, | ||
763 | .resume = ad7879_resume, | ||
764 | .id_table = ad7879_id, | ||
765 | }; | ||
766 | |||
767 | static int __init ad7879_init(void) | ||
768 | { | ||
769 | return i2c_add_driver(&ad7879_driver); | ||
770 | } | ||
771 | module_init(ad7879_init); | ||
772 | |||
773 | static void __exit ad7879_exit(void) | ||
774 | { | ||
775 | i2c_del_driver(&ad7879_driver); | ||
776 | } | ||
777 | module_exit(ad7879_exit); | ||
778 | #endif | ||
779 | |||
780 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
781 | MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver"); | ||
782 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 1d11e2be9ef8..dfa6a84ab50a 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -162,6 +162,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) | |||
162 | input_report_abs(wm->input_dev, ABS_X, x & 0xfff); | 162 | input_report_abs(wm->input_dev, ABS_X, x & 0xfff); |
163 | input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); | 163 | input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); |
164 | input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); | 164 | input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); |
165 | input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); | ||
165 | input_sync(wm->input_dev); | 166 | input_sync(wm->input_dev); |
166 | reads++; | 167 | reads++; |
167 | } while (reads < cinfo[sp_idx].reads); | 168 | } while (reads < cinfo[sp_idx].reads); |
@@ -245,7 +246,7 @@ static void wm97xx_irq_enable(struct wm97xx *wm, int enable) | |||
245 | if (enable) | 246 | if (enable) |
246 | enable_irq(wm->pen_irq); | 247 | enable_irq(wm->pen_irq); |
247 | else | 248 | else |
248 | disable_irq(wm->pen_irq); | 249 | disable_irq_nosync(wm->pen_irq); |
249 | } | 250 | } |
250 | 251 | ||
251 | static struct wm97xx_mach_ops mainstone_mach_ops = { | 252 | static struct wm97xx_mach_ops mainstone_mach_ops = { |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 54986627def0..e868264fe799 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -151,12 +151,14 @@ static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 | |||
151 | input_report_abs(idev, ABS_X, x); | 151 | input_report_abs(idev, ABS_X, x); |
152 | input_report_abs(idev, ABS_Y, y); | 152 | input_report_abs(idev, ABS_Y, y); |
153 | input_report_abs(idev, ABS_PRESSURE, pressure); | 153 | input_report_abs(idev, ABS_PRESSURE, pressure); |
154 | input_report_key(idev, BTN_TOUCH, 1); | ||
154 | input_sync(idev); | 155 | input_sync(idev); |
155 | } | 156 | } |
156 | 157 | ||
157 | static void ucb1400_ts_event_release(struct input_dev *idev) | 158 | static void ucb1400_ts_event_release(struct input_dev *idev) |
158 | { | 159 | { |
159 | input_report_abs(idev, ABS_PRESSURE, 0); | 160 | input_report_abs(idev, ABS_PRESSURE, 0); |
161 | input_report_key(idev, BTN_TOUCH, 0); | ||
160 | input_sync(idev); | 162 | input_sync(idev); |
161 | } | 163 | } |
162 | 164 | ||
@@ -377,7 +379,8 @@ static int ucb1400_ts_probe(struct platform_device *dev) | |||
377 | ucb->ts_idev->id.product = ucb->id; | 379 | ucb->ts_idev->id.product = ucb->id; |
378 | ucb->ts_idev->open = ucb1400_ts_open; | 380 | ucb->ts_idev->open = ucb1400_ts_open; |
379 | ucb->ts_idev->close = ucb1400_ts_close; | 381 | ucb->ts_idev->close = ucb1400_ts_close; |
380 | ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS); | 382 | ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
383 | ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
381 | 384 | ||
382 | ucb1400_adc_enable(ucb->ac97); | 385 | ucb1400_adc_enable(ucb->ac97); |
383 | x_res = ucb1400_ts_read_xres(ucb); | 386 | x_res = ucb1400_ts_read_xres(ucb); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index d15aa11d7056..cec480bffe38 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -409,6 +409,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) | |||
409 | wm->pen_is_down = 0; | 409 | wm->pen_is_down = 0; |
410 | dev_dbg(wm->dev, "pen up\n"); | 410 | dev_dbg(wm->dev, "pen up\n"); |
411 | input_report_abs(wm->input_dev, ABS_PRESSURE, 0); | 411 | input_report_abs(wm->input_dev, ABS_PRESSURE, 0); |
412 | input_report_key(wm->input_dev, BTN_TOUCH, 0); | ||
412 | input_sync(wm->input_dev); | 413 | input_sync(wm->input_dev); |
413 | } else if (!(rc & RC_AGAIN)) { | 414 | } else if (!(rc & RC_AGAIN)) { |
414 | /* We need high frequency updates only while | 415 | /* We need high frequency updates only while |
@@ -433,6 +434,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) | |||
433 | input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); | 434 | input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); |
434 | input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); | 435 | input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); |
435 | input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); | 436 | input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); |
437 | input_report_key(wm->input_dev, BTN_TOUCH, 1); | ||
436 | input_sync(wm->input_dev); | 438 | input_sync(wm->input_dev); |
437 | wm->pen_is_down = 1; | 439 | wm->pen_is_down = 1; |
438 | wm->ts_reader_interval = wm->ts_reader_min_interval; | 440 | wm->ts_reader_interval = wm->ts_reader_min_interval; |
@@ -628,18 +630,21 @@ static int wm97xx_probe(struct device *dev) | |||
628 | wm->input_dev->phys = "wm97xx"; | 630 | wm->input_dev->phys = "wm97xx"; |
629 | wm->input_dev->open = wm97xx_ts_input_open; | 631 | wm->input_dev->open = wm97xx_ts_input_open; |
630 | wm->input_dev->close = wm97xx_ts_input_close; | 632 | wm->input_dev->close = wm97xx_ts_input_close; |
631 | set_bit(EV_ABS, wm->input_dev->evbit); | 633 | |
632 | set_bit(ABS_X, wm->input_dev->absbit); | 634 | __set_bit(EV_ABS, wm->input_dev->evbit); |
633 | set_bit(ABS_Y, wm->input_dev->absbit); | 635 | __set_bit(EV_KEY, wm->input_dev->evbit); |
634 | set_bit(ABS_PRESSURE, wm->input_dev->absbit); | 636 | __set_bit(BTN_TOUCH, wm->input_dev->keybit); |
637 | |||
635 | input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1], | 638 | input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1], |
636 | abs_x[2], 0); | 639 | abs_x[2], 0); |
637 | input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1], | 640 | input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1], |
638 | abs_y[2], 0); | 641 | abs_y[2], 0); |
639 | input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1], | 642 | input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1], |
640 | abs_p[2], 0); | 643 | abs_p[2], 0); |
644 | |||
641 | input_set_drvdata(wm->input_dev, wm); | 645 | input_set_drvdata(wm->input_dev, wm); |
642 | wm->input_dev->dev.parent = dev; | 646 | wm->input_dev->dev.parent = dev; |
647 | |||
643 | ret = input_register_device(wm->input_dev); | 648 | ret = input_register_device(wm->input_dev); |
644 | if (ret < 0) | 649 | if (ret < 0) |
645 | goto dev_alloc_err; | 650 | goto dev_alloc_err; |
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c new file mode 100644 index 000000000000..41e4359c277c --- /dev/null +++ b/drivers/input/touchscreen/zylonite-wm97xx.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * zylonite-wm97xx.c -- Zylonite Continuous Touch screen driver | ||
3 | * | ||
4 | * Copyright 2004, 2007, 2008 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * Parts Copyright : Ian Molton <spyro@f2s.com> | ||
7 | * Andrew Zabolotny <zap@homelink.ru> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * Notes: | ||
15 | * This is a wm97xx extended touch driver supporting interrupt driven | ||
16 | * and continuous operation on Marvell Zylonite development systems | ||
17 | * (which have a WM9713 on board). | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/wm97xx.h> | ||
29 | |||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/mfp.h> | ||
32 | #include <mach/regs-ac97.h> | ||
33 | |||
34 | struct continuous { | ||
35 | u16 id; /* codec id */ | ||
36 | u8 code; /* continuous code */ | ||
37 | u8 reads; /* number of coord reads per read cycle */ | ||
38 | u32 speed; /* number of coords per second */ | ||
39 | }; | ||
40 | |||
41 | #define WM_READS(sp) ((sp / HZ) + 1) | ||
42 | |||
43 | static const struct continuous cinfo[] = { | ||
44 | { WM9713_ID2, 0, WM_READS(94), 94 }, | ||
45 | { WM9713_ID2, 1, WM_READS(120), 120 }, | ||
46 | { WM9713_ID2, 2, WM_READS(154), 154 }, | ||
47 | { WM9713_ID2, 3, WM_READS(188), 188 }, | ||
48 | }; | ||
49 | |||
50 | /* continuous speed index */ | ||
51 | static int sp_idx; | ||
52 | |||
53 | /* | ||
54 | * Pen sampling frequency (Hz) in continuous mode. | ||
55 | */ | ||
56 | static int cont_rate = 200; | ||
57 | module_param(cont_rate, int, 0); | ||
58 | MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); | ||
59 | |||
60 | /* | ||
61 | * Pressure readback. | ||
62 | * | ||
63 | * Set to 1 to read back pen down pressure | ||
64 | */ | ||
65 | static int pressure; | ||
66 | module_param(pressure, int, 0); | ||
67 | MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); | ||
68 | |||
69 | /* | ||
70 | * AC97 touch data slot. | ||
71 | * | ||
72 | * Touch screen readback data ac97 slot | ||
73 | */ | ||
74 | static int ac97_touch_slot = 5; | ||
75 | module_param(ac97_touch_slot, int, 0); | ||
76 | MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); | ||
77 | |||
78 | |||
79 | /* flush AC97 slot 5 FIFO machines */ | ||
80 | static void wm97xx_acc_pen_up(struct wm97xx *wm) | ||
81 | { | ||
82 | int i; | ||
83 | |||
84 | msleep(1); | ||
85 | |||
86 | for (i = 0; i < 16; i++) | ||
87 | MODR; | ||
88 | } | ||
89 | |||
90 | static int wm97xx_acc_pen_down(struct wm97xx *wm) | ||
91 | { | ||
92 | u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES; | ||
93 | int reads = 0; | ||
94 | static u16 last, tries; | ||
95 | |||
96 | /* When the AC97 queue has been drained we need to allow time | ||
97 | * to buffer up samples otherwise we end up spinning polling | ||
98 | * for samples. The controller can't have a suitably low | ||
99 | * threashold set to use the notifications it gives. | ||
100 | */ | ||
101 | msleep(1); | ||
102 | |||
103 | if (tries > 5) { | ||
104 | tries = 0; | ||
105 | return RC_PENUP; | ||
106 | } | ||
107 | |||
108 | x = MODR; | ||
109 | if (x == last) { | ||
110 | tries++; | ||
111 | return RC_AGAIN; | ||
112 | } | ||
113 | last = x; | ||
114 | do { | ||
115 | if (reads) | ||
116 | x = MODR; | ||
117 | y = MODR; | ||
118 | if (pressure) | ||
119 | p = MODR; | ||
120 | |||
121 | /* are samples valid */ | ||
122 | if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || | ||
123 | (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || | ||
124 | (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) | ||
125 | goto up; | ||
126 | |||
127 | /* coordinate is good */ | ||
128 | tries = 0; | ||
129 | input_report_abs(wm->input_dev, ABS_X, x & 0xfff); | ||
130 | input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); | ||
131 | input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); | ||
132 | input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); | ||
133 | input_sync(wm->input_dev); | ||
134 | reads++; | ||
135 | } while (reads < cinfo[sp_idx].reads); | ||
136 | up: | ||
137 | return RC_PENDOWN | RC_AGAIN; | ||
138 | } | ||
139 | |||
140 | static int wm97xx_acc_startup(struct wm97xx *wm) | ||
141 | { | ||
142 | int idx; | ||
143 | |||
144 | /* check we have a codec */ | ||
145 | if (wm->ac97 == NULL) | ||
146 | return -ENODEV; | ||
147 | |||
148 | /* Go you big red fire engine */ | ||
149 | for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { | ||
150 | if (wm->id != cinfo[idx].id) | ||
151 | continue; | ||
152 | sp_idx = idx; | ||
153 | if (cont_rate <= cinfo[idx].speed) | ||
154 | break; | ||
155 | } | ||
156 | wm->acc_rate = cinfo[sp_idx].code; | ||
157 | wm->acc_slot = ac97_touch_slot; | ||
158 | dev_info(wm->dev, | ||
159 | "zylonite accelerated touchscreen driver, %d samples/sec\n", | ||
160 | cinfo[sp_idx].speed); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static void wm97xx_irq_enable(struct wm97xx *wm, int enable) | ||
166 | { | ||
167 | if (enable) | ||
168 | enable_irq(wm->pen_irq); | ||
169 | else | ||
170 | disable_irq_nosync(wm->pen_irq); | ||
171 | } | ||
172 | |||
173 | static struct wm97xx_mach_ops zylonite_mach_ops = { | ||
174 | .acc_enabled = 1, | ||
175 | .acc_pen_up = wm97xx_acc_pen_up, | ||
176 | .acc_pen_down = wm97xx_acc_pen_down, | ||
177 | .acc_startup = wm97xx_acc_startup, | ||
178 | .irq_enable = wm97xx_irq_enable, | ||
179 | .irq_gpio = WM97XX_GPIO_2, | ||
180 | }; | ||
181 | |||
182 | static int zylonite_wm97xx_probe(struct platform_device *pdev) | ||
183 | { | ||
184 | struct wm97xx *wm = platform_get_drvdata(pdev); | ||
185 | int gpio_touch_irq; | ||
186 | |||
187 | if (cpu_is_pxa320()) | ||
188 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO15); | ||
189 | else | ||
190 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); | ||
191 | |||
192 | wm->pen_irq = IRQ_GPIO(gpio_touch_irq); | ||
193 | set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); | ||
194 | |||
195 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | ||
196 | WM97XX_GPIO_POL_HIGH, | ||
197 | WM97XX_GPIO_STICKY, | ||
198 | WM97XX_GPIO_WAKE); | ||
199 | wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT, | ||
200 | WM97XX_GPIO_POL_HIGH, | ||
201 | WM97XX_GPIO_NOTSTICKY, | ||
202 | WM97XX_GPIO_NOWAKE); | ||
203 | |||
204 | return wm97xx_register_mach_ops(wm, &zylonite_mach_ops); | ||
205 | } | ||
206 | |||
207 | static int zylonite_wm97xx_remove(struct platform_device *pdev) | ||
208 | { | ||
209 | struct wm97xx *wm = platform_get_drvdata(pdev); | ||
210 | |||
211 | wm97xx_unregister_mach_ops(wm); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct platform_driver zylonite_wm97xx_driver = { | ||
217 | .probe = zylonite_wm97xx_probe, | ||
218 | .remove = zylonite_wm97xx_remove, | ||
219 | .driver = { | ||
220 | .name = "wm97xx-touch", | ||
221 | }, | ||
222 | }; | ||
223 | |||
224 | static int __init zylonite_wm97xx_init(void) | ||
225 | { | ||
226 | return platform_driver_register(&zylonite_wm97xx_driver); | ||
227 | } | ||
228 | |||
229 | static void __exit zylonite_wm97xx_exit(void) | ||
230 | { | ||
231 | platform_driver_unregister(&zylonite_wm97xx_driver); | ||
232 | } | ||
233 | |||
234 | module_init(zylonite_wm97xx_init); | ||
235 | module_exit(zylonite_wm97xx_exit); | ||
236 | |||
237 | /* Module information */ | ||
238 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
239 | MODULE_DESCRIPTION("wm97xx continuous touch driver for Zylonite"); | ||
240 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 102ef4a14c5f..d2109054de85 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -82,7 +82,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
82 | if (!gpio_is_valid(template->gpio)) { | 82 | if (!gpio_is_valid(template->gpio)) { |
83 | printk(KERN_INFO "Skipping unavilable LED gpio %d (%s)\n", | 83 | printk(KERN_INFO "Skipping unavilable LED gpio %d (%s)\n", |
84 | template->gpio, template->name); | 84 | template->gpio, template->name); |
85 | return; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | ret = gpio_request(template->gpio, template->name); | 88 | ret = gpio_request(template->gpio, template->name); |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 772990415f99..68eb4493f991 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -28,25 +28,12 @@ config DVB_AV7110 | |||
28 | download/extract it, and then copy it to /usr/lib/hotplug/firmware | 28 | download/extract it, and then copy it to /usr/lib/hotplug/firmware |
29 | or /lib/firmware (depending on configuration of firmware hotplug). | 29 | or /lib/firmware (depending on configuration of firmware hotplug). |
30 | 30 | ||
31 | Say Y if you own such a card and want to use it. | 31 | Alternatively, you can download the file and use the kernel's |
32 | 32 | EXTRA_FIRMWARE configuration option to build it into your | |
33 | config DVB_AV7110_FIRMWARE | 33 | kernel image by adding the filename to the EXTRA_FIRMWARE |
34 | bool "Compile AV7110 firmware into the driver" | 34 | configuration option string. |
35 | depends on DVB_AV7110 && !STANDALONE | ||
36 | default y if DVB_AV7110=y | ||
37 | help | ||
38 | The AV7110 firmware is normally loaded by the firmware hotplug manager. | ||
39 | If you want to compile the firmware into the driver you need to say | ||
40 | Y here and provide the correct path of the firmware. You need this | ||
41 | option if you want to compile the whole driver statically into the | ||
42 | kernel. | ||
43 | 35 | ||
44 | All other people say N. | 36 | Say Y if you own such a card and want to use it. |
45 | |||
46 | config DVB_AV7110_FIRMWARE_FILE | ||
47 | string "Full pathname of av7110 firmware file" | ||
48 | depends on DVB_AV7110_FIRMWARE | ||
49 | default "/usr/lib/hotplug/firmware/dvb-ttpci-01.fw" | ||
50 | 37 | ||
51 | config DVB_AV7110_OSD | 38 | config DVB_AV7110_OSD |
52 | bool "AV7110 OSD support" | 39 | bool "AV7110 OSD support" |
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile index 71451237294c..8a4d5bb20a5b 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/dvb/ttpci/Makefile | |||
@@ -19,12 +19,3 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o | |||
19 | 19 | ||
20 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 20 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
21 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 21 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
22 | |||
23 | hostprogs-y := fdump | ||
24 | |||
25 | ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y) | ||
26 | $(obj)/av7110.o: $(obj)/av7110_firm.h | ||
27 | |||
28 | $(obj)/av7110_firm.h: $(obj)/fdump | ||
29 | $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@ | ||
30 | endif | ||
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 4624cee93e74..d1d959ed37b7 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -1518,20 +1518,6 @@ static int check_firmware(struct av7110* av7110) | |||
1518 | return 0; | 1518 | return 0; |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | #ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE | ||
1522 | #include "av7110_firm.h" | ||
1523 | static void put_firmware(struct av7110* av7110) | ||
1524 | { | ||
1525 | av7110->bin_fw = NULL; | ||
1526 | } | ||
1527 | |||
1528 | static inline int get_firmware(struct av7110* av7110) | ||
1529 | { | ||
1530 | av7110->bin_fw = dvb_ttpci_fw; | ||
1531 | av7110->size_fw = sizeof(dvb_ttpci_fw); | ||
1532 | return check_firmware(av7110); | ||
1533 | } | ||
1534 | #else | ||
1535 | static void put_firmware(struct av7110* av7110) | 1521 | static void put_firmware(struct av7110* av7110) |
1536 | { | 1522 | { |
1537 | vfree(av7110->bin_fw); | 1523 | vfree(av7110->bin_fw); |
@@ -1580,8 +1566,6 @@ static int get_firmware(struct av7110* av7110) | |||
1580 | release_firmware(fw); | 1566 | release_firmware(fw); |
1581 | return ret; | 1567 | return ret; |
1582 | } | 1568 | } |
1583 | #endif | ||
1584 | |||
1585 | 1569 | ||
1586 | static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) | 1570 | static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) |
1587 | { | 1571 | { |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 3a3f5279e927..5e3f88911a1d 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
@@ -198,29 +198,10 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) | |||
198 | 198 | ||
199 | /* we cannot write av7110 DRAM directly, so load a bootloader into | 199 | /* we cannot write av7110 DRAM directly, so load a bootloader into |
200 | * the DPRAM which implements a simple boot protocol */ | 200 | * the DPRAM which implements a simple boot protocol */ |
201 | static u8 bootcode[] = { | ||
202 | 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04, | ||
203 | 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04, | ||
204 | 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24, | ||
205 | 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34, | ||
206 | 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55, | ||
207 | 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74, | ||
208 | 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04, | ||
209 | 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64, | ||
210 | 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02, | ||
211 | 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0, | ||
212 | 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d, | ||
213 | 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f, | ||
214 | 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0, | ||
215 | 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, | ||
216 | 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01, | ||
217 | 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec, | ||
218 | 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00, | ||
219 | 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0 | ||
220 | }; | ||
221 | |||
222 | int av7110_bootarm(struct av7110 *av7110) | 201 | int av7110_bootarm(struct av7110 *av7110) |
223 | { | 202 | { |
203 | const struct firmware *fw; | ||
204 | const char *fw_name = "av7110/bootcode.bin"; | ||
224 | struct saa7146_dev *dev = av7110->dev; | 205 | struct saa7146_dev *dev = av7110->dev; |
225 | u32 ret; | 206 | u32 ret; |
226 | int i; | 207 | int i; |
@@ -261,7 +242,15 @@ int av7110_bootarm(struct av7110 *av7110) | |||
261 | //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); | 242 | //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); |
262 | //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); | 243 | //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); |
263 | 244 | ||
264 | mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); | 245 | ret = request_firmware(&fw, fw_name, &dev->pci->dev); |
246 | if (ret) { | ||
247 | printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n", | ||
248 | fw_name); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size); | ||
253 | release_firmware(fw); | ||
265 | iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); | 254 | iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); |
266 | 255 | ||
267 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { | 256 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { |
@@ -302,7 +291,7 @@ int av7110_bootarm(struct av7110 *av7110) | |||
302 | av7110->arm_ready = 1; | 291 | av7110->arm_ready = 1; |
303 | return 0; | 292 | return 0; |
304 | } | 293 | } |
305 | 294 | MODULE_FIRMWARE("av7110/bootcode.bin"); | |
306 | 295 | ||
307 | /**************************************************************************** | 296 | /**************************************************************************** |
308 | * DEBI command polling | 297 | * DEBI command polling |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h index ca99e5c1fc8a..1634aba5cb84 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/dvb/ttpci/av7110_hw.h | |||
@@ -390,7 +390,8 @@ static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, | |||
390 | } | 390 | } |
391 | 391 | ||
392 | /* buffer writes */ | 392 | /* buffer writes */ |
393 | static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, u8 *val, int count) | 393 | static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, |
394 | const u8 *val, int count) | ||
394 | { | 395 | { |
395 | memcpy(av7110->debi_virt, val, count); | 396 | memcpy(av7110->debi_virt, val, count); |
396 | av7110_debiwrite(av7110, config, addr, 0, count); | 397 | av7110_debiwrite(av7110, config, addr, 0, count); |
diff --git a/drivers/media/dvb/ttpci/fdump.c b/drivers/media/dvb/ttpci/fdump.c deleted file mode 100644 index c90001d35e7d..000000000000 --- a/drivers/media/dvb/ttpci/fdump.c +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <sys/types.h> | ||
3 | #include <sys/stat.h> | ||
4 | #include <fcntl.h> | ||
5 | #include <unistd.h> | ||
6 | |||
7 | int main(int argc, char **argv) | ||
8 | { | ||
9 | unsigned char buf[8]; | ||
10 | unsigned int i, count, bytes = 0; | ||
11 | FILE *fd_in, *fd_out; | ||
12 | |||
13 | if (argc != 4) { | ||
14 | fprintf(stderr, "\n\tusage: %s <ucode.bin> <array_name> <output_name>\n\n", argv[0]); | ||
15 | return -1; | ||
16 | } | ||
17 | |||
18 | fd_in = fopen(argv[1], "rb"); | ||
19 | if (fd_in == NULL) { | ||
20 | fprintf(stderr, "firmware file '%s' not found\n", argv[1]); | ||
21 | return -1; | ||
22 | } | ||
23 | |||
24 | fd_out = fopen(argv[3], "w+"); | ||
25 | if (fd_out == NULL) { | ||
26 | fprintf(stderr, "cannot create output file '%s'\n", argv[3]); | ||
27 | return -1; | ||
28 | } | ||
29 | |||
30 | fprintf(fd_out, "\n#include <asm/types.h>\n\nu8 %s [] = {", argv[2]); | ||
31 | |||
32 | while ((count = fread(buf, 1, 8, fd_in)) > 0) { | ||
33 | fprintf(fd_out, "\n\t"); | ||
34 | for (i = 0; i < count; i++, bytes++) | ||
35 | fprintf(fd_out, "0x%02x, ", buf[i]); | ||
36 | } | ||
37 | |||
38 | fprintf(fd_out, "\n};\n\n"); | ||
39 | |||
40 | fclose(fd_in); | ||
41 | fclose(fd_out); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index 7cce3342ef8c..606aa58afdea 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c | |||
@@ -299,13 +299,14 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | |||
299 | struct mlx4_cmd_mailbox *mailbox; | 299 | struct mlx4_cmd_mailbox *mailbox; |
300 | int err; | 300 | int err; |
301 | 301 | ||
302 | if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) | ||
303 | return 0; | ||
304 | |||
302 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 305 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
303 | if (IS_ERR(mailbox)) | 306 | if (IS_ERR(mailbox)) |
304 | return PTR_ERR(mailbox); | 307 | return PTR_ERR(mailbox); |
305 | 308 | ||
306 | memset(mailbox->buf, 0, 256); | 309 | memset(mailbox->buf, 0, 256); |
307 | if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) | ||
308 | return 0; | ||
309 | 310 | ||
310 | ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; | 311 | ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; |
311 | err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, | 312 | err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 912308eec865..329f890e2903 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -369,7 +369,7 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, | |||
369 | * MN10300/AM33 configuration | 369 | * MN10300/AM33 configuration |
370 | */ | 370 | */ |
371 | 371 | ||
372 | #include <asm/unit/smc91111.h> | 372 | #include <unit/smc91111.h> |
373 | 373 | ||
374 | #else | 374 | #else |
375 | 375 | ||
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 25a00ce4f24d..fa3a11365ec3 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -173,12 +173,21 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) | |||
173 | struct dmar_drhd_unit *dmaru; | 173 | struct dmar_drhd_unit *dmaru; |
174 | int ret = 0; | 174 | int ret = 0; |
175 | 175 | ||
176 | drhd = (struct acpi_dmar_hardware_unit *)header; | ||
177 | if (!drhd->address) { | ||
178 | /* Promote an attitude of violence to a BIOS engineer today */ | ||
179 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
180 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
181 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
182 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
183 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
184 | return -ENODEV; | ||
185 | } | ||
176 | dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); | 186 | dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); |
177 | if (!dmaru) | 187 | if (!dmaru) |
178 | return -ENOMEM; | 188 | return -ENOMEM; |
179 | 189 | ||
180 | dmaru->hdr = header; | 190 | dmaru->hdr = header; |
181 | drhd = (struct acpi_dmar_hardware_unit *)header; | ||
182 | dmaru->reg_base_addr = drhd->address; | 191 | dmaru->reg_base_addr = drhd->address; |
183 | dmaru->segment = drhd->segment; | 192 | dmaru->segment = drhd->segment; |
184 | dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ | 193 | dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fb3a3f3fca7a..001b328adf80 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -733,8 +733,8 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) | |||
733 | start &= (((u64)1) << addr_width) - 1; | 733 | start &= (((u64)1) << addr_width) - 1; |
734 | end &= (((u64)1) << addr_width) - 1; | 734 | end &= (((u64)1) << addr_width) - 1; |
735 | /* in case it's partial page */ | 735 | /* in case it's partial page */ |
736 | start = PAGE_ALIGN(start); | 736 | start &= PAGE_MASK; |
737 | end &= PAGE_MASK; | 737 | end = PAGE_ALIGN(end); |
738 | npages = (end - start) / VTD_PAGE_SIZE; | 738 | npages = (end - start) / VTD_PAGE_SIZE; |
739 | 739 | ||
740 | /* we don't need lock here, nobody else touches the iova range */ | 740 | /* we don't need lock here, nobody else touches the iova range */ |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 687dcf2d0154..5defe5ea5eda 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -1663,7 +1663,7 @@ qla1280_load_firmware_pio(struct scsi_qla_host *ha) | |||
1663 | 1663 | ||
1664 | /* Load RISC code. */ | 1664 | /* Load RISC code. */ |
1665 | risc_address = ha->fwstart; | 1665 | risc_address = ha->fwstart; |
1666 | fw_data = (const __le16 *)&fw->data[4]; | 1666 | fw_data = (const __le16 *)&fw->data[6]; |
1667 | risc_code_size = (fw->size - 6) / 2; | 1667 | risc_code_size = (fw->size - 6) / 2; |
1668 | 1668 | ||
1669 | for (i = 0; i < risc_code_size; i++) { | 1669 | for (i = 0; i < risc_code_size; i++) { |
@@ -1722,7 +1722,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha) | |||
1722 | 1722 | ||
1723 | /* Load RISC code. */ | 1723 | /* Load RISC code. */ |
1724 | risc_address = ha->fwstart; | 1724 | risc_address = ha->fwstart; |
1725 | fw_data = (const __le16 *)&fw->data[4]; | 1725 | fw_data = (const __le16 *)&fw->data[6]; |
1726 | risc_code_size = (fw->size - 6) / 2; | 1726 | risc_code_size = (fw->size - 6) / 2; |
1727 | 1727 | ||
1728 | dprintk(1, "%s: DMA RISC code (%i) words\n", | 1728 | dprintk(1, "%s: DMA RISC code (%i) words\n", |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index e1850904ff73..fbc83bebdd8e 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -38,9 +38,6 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) | |||
38 | { }; | 38 | { }; |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | /* scsi_scan.c */ | ||
42 | int scsi_complete_async_scans(void); | ||
43 | |||
44 | /* scsi_devinfo.c */ | 41 | /* scsi_devinfo.c */ |
45 | extern int scsi_get_device_flags(struct scsi_device *sdev, | 42 | extern int scsi_get_device_flags(struct scsi_device *sdev, |
46 | const unsigned char *vendor, | 43 | const unsigned char *vendor, |
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c index 8a636103083d..2f21af21269a 100644 --- a/drivers/scsi/scsi_wait_scan.c +++ b/drivers/scsi/scsi_wait_scan.c | |||
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include "scsi_priv.h" | 14 | #include <scsi/scsi_scan.h> |
15 | 15 | ||
16 | static int __init wait_scan_init(void) | 16 | static int __init wait_scan_init(void) |
17 | { | 17 | { |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0328fd4006e5..343e3a35b6a3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -854,7 +854,7 @@ config SERIAL_IMX_CONSOLE | |||
854 | 854 | ||
855 | config SERIAL_UARTLITE | 855 | config SERIAL_UARTLITE |
856 | tristate "Xilinx uartlite serial port support" | 856 | tristate "Xilinx uartlite serial port support" |
857 | depends on PPC32 | 857 | depends on PPC32 || MICROBLAZE |
858 | select SERIAL_CORE | 858 | select SERIAL_CORE |
859 | help | 859 | help |
860 | Say Y here if you want to use the Xilinx uartlite serial controller. | 860 | Say Y here if you want to use the Xilinx uartlite serial controller. |
@@ -1340,7 +1340,7 @@ config SERIAL_NETX_CONSOLE | |||
1340 | 1340 | ||
1341 | config SERIAL_OF_PLATFORM | 1341 | config SERIAL_OF_PLATFORM |
1342 | tristate "Serial port on Open Firmware platform bus" | 1342 | tristate "Serial port on Open Firmware platform bus" |
1343 | depends on PPC_OF | 1343 | depends on PPC_OF || MICROBLAZE |
1344 | depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL | 1344 | depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL |
1345 | help | 1345 | help |
1346 | If you have a PowerPC based system that has serial ports | 1346 | If you have a PowerPC based system that has serial ports |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 63024145215d..5eb8f21da82e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -240,8 +240,6 @@ config ORION5X_WATCHDOG | |||
240 | To compile this driver as a module, choose M here: the | 240 | To compile this driver as a module, choose M here: the |
241 | module will be called orion5x_wdt. | 241 | module will be called orion5x_wdt. |
242 | 242 | ||
243 | # ARM26 Architecture | ||
244 | |||
245 | # AVR32 Architecture | 243 | # AVR32 Architecture |
246 | 244 | ||
247 | config AT32AP700X_WDT | 245 | config AT32AP700X_WDT |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 806b3eb08536..7f8c56b14f58 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -42,8 +42,6 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | |||
42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | 42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o |
43 | obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o | 43 | obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o |
44 | 44 | ||
45 | # ARM26 Architecture | ||
46 | |||
47 | # AVR32 Architecture | 45 | # AVR32 Architecture |
48 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
49 | 47 | ||
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index e35d54589232..29e52c237a3b 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c | |||
@@ -197,7 +197,7 @@ static struct miscdevice at91wdt_miscdev = { | |||
197 | .fops = &at91wdt_fops, | 197 | .fops = &at91wdt_fops, |
198 | }; | 198 | }; |
199 | 199 | ||
200 | static int __init at91wdt_probe(struct platform_device *pdev) | 200 | static int __devinit at91wdt_probe(struct platform_device *pdev) |
201 | { | 201 | { |
202 | int res; | 202 | int res; |
203 | 203 | ||
@@ -214,7 +214,7 @@ static int __init at91wdt_probe(struct platform_device *pdev) | |||
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | static int __exit at91wdt_remove(struct platform_device *pdev) | 217 | static int __devexit at91wdt_remove(struct platform_device *pdev) |
218 | { | 218 | { |
219 | int res; | 219 | int res; |
220 | 220 | ||
@@ -252,7 +252,7 @@ static int at91wdt_resume(struct platform_device *pdev) | |||
252 | 252 | ||
253 | static struct platform_driver at91wdt_driver = { | 253 | static struct platform_driver at91wdt_driver = { |
254 | .probe = at91wdt_probe, | 254 | .probe = at91wdt_probe, |
255 | .remove = __exit_p(at91wdt_remove), | 255 | .remove = __devexit_p(at91wdt_remove), |
256 | .shutdown = at91wdt_shutdown, | 256 | .shutdown = at91wdt_shutdown, |
257 | .suspend = at91wdt_suspend, | 257 | .suspend = at91wdt_suspend, |
258 | .resume = at91wdt_resume, | 258 | .resume = at91wdt_resume, |
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 2dbe83570d65..7ba0b11ec525 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c | |||
@@ -52,10 +52,10 @@ | |||
52 | #define ESB_LOCK_REG 0x68 /* WDT lock register */ | 52 | #define ESB_LOCK_REG 0x68 /* WDT lock register */ |
53 | 53 | ||
54 | /* Memory mapped registers */ | 54 | /* Memory mapped registers */ |
55 | #define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */ | 55 | #define ESB_TIMER1_REG (BASEADDR + 0x00)/* Timer1 value after each reset */ |
56 | #define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */ | 56 | #define ESB_TIMER2_REG (BASEADDR + 0x04)/* Timer2 value after each reset */ |
57 | #define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */ | 57 | #define ESB_GINTSR_REG (BASEADDR + 0x08)/* General Interrupt Status Register */ |
58 | #define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ | 58 | #define ESB_RELOAD_REG (BASEADDR + 0x0c)/* Reload register */ |
59 | 59 | ||
60 | /* Lock register bits */ | 60 | /* Lock register bits */ |
61 | #define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ | 61 | #define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ |
@@ -68,6 +68,7 @@ | |||
68 | #define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ | 68 | #define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ |
69 | 69 | ||
70 | /* Reload register bits */ | 70 | /* Reload register bits */ |
71 | #define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ | ||
71 | #define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ | 72 | #define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ |
72 | 73 | ||
73 | /* Magic constants */ | 74 | /* Magic constants */ |
@@ -87,7 +88,6 @@ static struct platform_device *esb_platform_device; | |||
87 | /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ | 88 | /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ |
88 | #define WATCHDOG_HEARTBEAT 30 | 89 | #define WATCHDOG_HEARTBEAT 30 |
89 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 90 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
90 | |||
91 | module_param(heartbeat, int, 0); | 91 | module_param(heartbeat, int, 0); |
92 | MODULE_PARM_DESC(heartbeat, | 92 | MODULE_PARM_DESC(heartbeat, |
93 | "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" | 93 | "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" |
@@ -123,7 +123,7 @@ static int esb_timer_start(void) | |||
123 | esb_unlock_registers(); | 123 | esb_unlock_registers(); |
124 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | 124 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); |
125 | /* Enable or Enable + Lock? */ | 125 | /* Enable or Enable + Lock? */ |
126 | val = 0x02 | (nowayout ? 0x01 : 0x00); | 126 | val = ESB_WDT_ENABLE | (nowayout ? ESB_WDT_LOCK : 0x00); |
127 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); | 127 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); |
128 | spin_unlock(&esb_lock); | 128 | spin_unlock(&esb_lock); |
129 | return 0; | 129 | return 0; |
@@ -143,7 +143,7 @@ static int esb_timer_stop(void) | |||
143 | spin_unlock(&esb_lock); | 143 | spin_unlock(&esb_lock); |
144 | 144 | ||
145 | /* Returns 0 if the timer was disabled, non-zero otherwise */ | 145 | /* Returns 0 if the timer was disabled, non-zero otherwise */ |
146 | return (val & 0x01); | 146 | return val & ESB_WDT_ENABLE; |
147 | } | 147 | } |
148 | 148 | ||
149 | static void esb_timer_keepalive(void) | 149 | static void esb_timer_keepalive(void) |
@@ -190,18 +190,6 @@ static int esb_timer_set_heartbeat(int time) | |||
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int esb_timer_read(void) | ||
194 | { | ||
195 | u32 count; | ||
196 | |||
197 | /* This isn't documented, and doesn't take into | ||
198 | * acount which stage is running, but it looks | ||
199 | * like a 20 bit count down, so we might as well report it. | ||
200 | */ | ||
201 | pci_read_config_dword(esb_pci, 0x64, &count); | ||
202 | return (int)count; | ||
203 | } | ||
204 | |||
205 | /* | 193 | /* |
206 | * /dev/watchdog handling | 194 | * /dev/watchdog handling |
207 | */ | 195 | */ |
@@ -282,7 +270,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
282 | sizeof(ident)) ? -EFAULT : 0; | 270 | sizeof(ident)) ? -EFAULT : 0; |
283 | 271 | ||
284 | case WDIOC_GETSTATUS: | 272 | case WDIOC_GETSTATUS: |
285 | return put_user(esb_timer_read(), p); | 273 | return put_user(0, p); |
286 | 274 | ||
287 | case WDIOC_GETBOOTSTATUS: | 275 | case WDIOC_GETBOOTSTATUS: |
288 | return put_user(triggered, p); | 276 | return put_user(triggered, p); |
@@ -362,8 +350,6 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); | |||
362 | 350 | ||
363 | static unsigned char __devinit esb_getdevice(void) | 351 | static unsigned char __devinit esb_getdevice(void) |
364 | { | 352 | { |
365 | u8 val1; | ||
366 | unsigned short val2; | ||
367 | /* | 353 | /* |
368 | * Find the PCI device | 354 | * Find the PCI device |
369 | */ | 355 | */ |
@@ -371,66 +357,79 @@ static unsigned char __devinit esb_getdevice(void) | |||
371 | esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, | 357 | esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, |
372 | PCI_DEVICE_ID_INTEL_ESB_9, NULL); | 358 | PCI_DEVICE_ID_INTEL_ESB_9, NULL); |
373 | 359 | ||
374 | if (esb_pci) { | 360 | if (!esb_pci) |
375 | if (pci_enable_device(esb_pci)) { | 361 | return 0; |
376 | printk(KERN_ERR PFX "failed to enable device\n"); | ||
377 | goto err_devput; | ||
378 | } | ||
379 | 362 | ||
380 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { | 363 | if (pci_enable_device(esb_pci)) { |
381 | printk(KERN_ERR PFX "failed to request region\n"); | 364 | printk(KERN_ERR PFX "failed to enable device\n"); |
382 | goto err_disable; | 365 | goto err_devput; |
383 | } | 366 | } |
384 | 367 | ||
385 | BASEADDR = pci_ioremap_bar(esb_pci, 0); | 368 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { |
386 | if (BASEADDR == NULL) { | 369 | printk(KERN_ERR PFX "failed to request region\n"); |
387 | /* Something's wrong here, BASEADDR has to be set */ | 370 | goto err_disable; |
388 | printk(KERN_ERR PFX "failed to get BASEADDR\n"); | 371 | } |
389 | goto err_release; | ||
390 | } | ||
391 | 372 | ||
392 | /* | 373 | BASEADDR = pci_ioremap_bar(esb_pci, 0); |
393 | * The watchdog has two timers, it can be setup so that the | 374 | if (BASEADDR == NULL) { |
394 | * expiry of timer1 results in an interrupt and the expiry of | 375 | /* Something's wrong here, BASEADDR has to be set */ |
395 | * timer2 results in a reboot. We set it to not generate | 376 | printk(KERN_ERR PFX "failed to get BASEADDR\n"); |
396 | * any interrupts as there is not much we can do with it | 377 | goto err_release; |
397 | * right now. | 378 | } |
398 | * | 379 | |
399 | * We also enable reboots and set the timer frequency to | 380 | /* Done */ |
400 | * the PCI clock divided by 2^15 (approx 1KHz). | 381 | return 1; |
401 | */ | ||
402 | pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); | ||
403 | |||
404 | /* Check that the WDT isn't already locked */ | ||
405 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); | ||
406 | if (val1 & ESB_WDT_LOCK) | ||
407 | printk(KERN_WARNING PFX "nowayout already set\n"); | ||
408 | |||
409 | /* Set the timer to watchdog mode and disable it for now */ | ||
410 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); | ||
411 | |||
412 | /* Check if the watchdog was previously triggered */ | ||
413 | esb_unlock_registers(); | ||
414 | val2 = readw(ESB_RELOAD_REG); | ||
415 | triggered = (val2 & (0x01 << 9) >> 9); | ||
416 | |||
417 | /* Reset trigger flag and timers */ | ||
418 | esb_unlock_registers(); | ||
419 | writew((0x11 << 8), ESB_RELOAD_REG); | ||
420 | |||
421 | /* Done */ | ||
422 | return 1; | ||
423 | 382 | ||
424 | err_release: | 383 | err_release: |
425 | pci_release_region(esb_pci, 0); | 384 | pci_release_region(esb_pci, 0); |
426 | err_disable: | 385 | err_disable: |
427 | pci_disable_device(esb_pci); | 386 | pci_disable_device(esb_pci); |
428 | err_devput: | 387 | err_devput: |
429 | pci_dev_put(esb_pci); | 388 | pci_dev_put(esb_pci); |
430 | } | ||
431 | return 0; | 389 | return 0; |
432 | } | 390 | } |
433 | 391 | ||
392 | static void __devinit esb_initdevice(void) | ||
393 | { | ||
394 | u8 val1; | ||
395 | u16 val2; | ||
396 | |||
397 | /* | ||
398 | * Config register: | ||
399 | * Bit 5 : 0 = Enable WDT_OUTPUT | ||
400 | * Bit 2 : 0 = set the timer frequency to the PCI clock | ||
401 | * divided by 2^15 (approx 1KHz). | ||
402 | * Bits 1:0 : 11 = WDT_INT_TYPE Disabled. | ||
403 | * The watchdog has two timers, it can be setup so that the | ||
404 | * expiry of timer1 results in an interrupt and the expiry of | ||
405 | * timer2 results in a reboot. We set it to not generate | ||
406 | * any interrupts as there is not much we can do with it | ||
407 | * right now. | ||
408 | */ | ||
409 | pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); | ||
410 | |||
411 | /* Check that the WDT isn't already locked */ | ||
412 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); | ||
413 | if (val1 & ESB_WDT_LOCK) | ||
414 | printk(KERN_WARNING PFX "nowayout already set\n"); | ||
415 | |||
416 | /* Set the timer to watchdog mode and disable it for now */ | ||
417 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); | ||
418 | |||
419 | /* Check if the watchdog was previously triggered */ | ||
420 | esb_unlock_registers(); | ||
421 | val2 = readw(ESB_RELOAD_REG); | ||
422 | if (val2 & ESB_WDT_TIMEOUT) | ||
423 | triggered = WDIOF_CARDRESET; | ||
424 | |||
425 | /* Reset WDT_TIMEOUT flag and timers */ | ||
426 | esb_unlock_registers(); | ||
427 | writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG); | ||
428 | |||
429 | /* And set the correct timeout value */ | ||
430 | esb_timer_set_heartbeat(heartbeat); | ||
431 | } | ||
432 | |||
434 | static int __devinit esb_probe(struct platform_device *dev) | 433 | static int __devinit esb_probe(struct platform_device *dev) |
435 | { | 434 | { |
436 | int ret; | 435 | int ret; |
@@ -441,13 +440,17 @@ static int __devinit esb_probe(struct platform_device *dev) | |||
441 | 440 | ||
442 | /* Check that the heartbeat value is within it's range; | 441 | /* Check that the heartbeat value is within it's range; |
443 | if not reset to the default */ | 442 | if not reset to the default */ |
444 | if (esb_timer_set_heartbeat(heartbeat)) { | 443 | if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) { |
445 | esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT); | 444 | heartbeat = WATCHDOG_HEARTBEAT; |
446 | printk(KERN_INFO PFX | 445 | printk(KERN_INFO PFX |
447 | "heartbeat value must be 1<heartbeat<2046, using %d\n", | 446 | "heartbeat value must be 1<heartbeat<2046, using %d\n", |
448 | heartbeat); | 447 | heartbeat); |
449 | } | 448 | } |
450 | 449 | ||
450 | /* Initialize the watchdog and make sure it does not run */ | ||
451 | esb_initdevice(); | ||
452 | |||
453 | /* Register the watchdog so that userspace has access to it */ | ||
451 | ret = misc_register(&esb_miscdev); | 454 | ret = misc_register(&esb_miscdev); |
452 | if (ret != 0) { | 455 | if (ret != 0) { |
453 | printk(KERN_ERR PFX | 456 | printk(KERN_ERR PFX |
@@ -455,7 +458,6 @@ static int __devinit esb_probe(struct platform_device *dev) | |||
455 | WATCHDOG_MINOR, ret); | 458 | WATCHDOG_MINOR, ret); |
456 | goto err_unmap; | 459 | goto err_unmap; |
457 | } | 460 | } |
458 | esb_timer_stop(); | ||
459 | printk(KERN_INFO PFX | 461 | printk(KERN_INFO PFX |
460 | "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", | 462 | "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", |
461 | BASEADDR, heartbeat, nowayout); | 463 | BASEADDR, heartbeat, nowayout); |
@@ -463,11 +465,8 @@ static int __devinit esb_probe(struct platform_device *dev) | |||
463 | 465 | ||
464 | err_unmap: | 466 | err_unmap: |
465 | iounmap(BASEADDR); | 467 | iounmap(BASEADDR); |
466 | /* err_release: */ | ||
467 | pci_release_region(esb_pci, 0); | 468 | pci_release_region(esb_pci, 0); |
468 | /* err_disable: */ | ||
469 | pci_disable_device(esb_pci); | 469 | pci_disable_device(esb_pci); |
470 | /* err_devput: */ | ||
471 | pci_dev_put(esb_pci); | 470 | pci_dev_put(esb_pci); |
472 | return ret; | 471 | return ret; |
473 | } | 472 | } |
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 74c92d384112..ae3832110acb 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c | |||
@@ -221,7 +221,7 @@ static struct miscdevice ks8695wdt_miscdev = { | |||
221 | .fops = &ks8695wdt_fops, | 221 | .fops = &ks8695wdt_fops, |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static int __init ks8695wdt_probe(struct platform_device *pdev) | 224 | static int __devinit ks8695wdt_probe(struct platform_device *pdev) |
225 | { | 225 | { |
226 | int res; | 226 | int res; |
227 | 227 | ||
@@ -238,7 +238,7 @@ static int __init ks8695wdt_probe(struct platform_device *pdev) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int __exit ks8695wdt_remove(struct platform_device *pdev) | 241 | static int __devexit ks8695wdt_remove(struct platform_device *pdev) |
242 | { | 242 | { |
243 | int res; | 243 | int res; |
244 | 244 | ||
@@ -276,7 +276,7 @@ static int ks8695wdt_resume(struct platform_device *pdev) | |||
276 | 276 | ||
277 | static struct platform_driver ks8695wdt_driver = { | 277 | static struct platform_driver ks8695wdt_driver = { |
278 | .probe = ks8695wdt_probe, | 278 | .probe = ks8695wdt_probe, |
279 | .remove = __exit_p(ks8695wdt_remove), | 279 | .remove = __devexit_p(ks8695wdt_remove), |
280 | .shutdown = ks8695wdt_shutdown, | 280 | .shutdown = ks8695wdt_shutdown, |
281 | .suspend = ks8695wdt_suspend, | 281 | .suspend = ks8695wdt_suspend, |
282 | .resume = ks8695wdt_resume, | 282 | .resume = ks8695wdt_resume, |
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index aa5ad6e33f02..f2713851aaab 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -258,7 +258,7 @@ static const struct file_operations omap_wdt_fops = { | |||
258 | .release = omap_wdt_release, | 258 | .release = omap_wdt_release, |
259 | }; | 259 | }; |
260 | 260 | ||
261 | static int __init omap_wdt_probe(struct platform_device *pdev) | 261 | static int __devinit omap_wdt_probe(struct platform_device *pdev) |
262 | { | 262 | { |
263 | struct resource *res, *mem; | 263 | struct resource *res, *mem; |
264 | struct omap_wdt_dev *wdev; | 264 | struct omap_wdt_dev *wdev; |
@@ -367,7 +367,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev) | |||
367 | omap_wdt_disable(wdev); | 367 | omap_wdt_disable(wdev); |
368 | } | 368 | } |
369 | 369 | ||
370 | static int omap_wdt_remove(struct platform_device *pdev) | 370 | static int __devexit omap_wdt_remove(struct platform_device *pdev) |
371 | { | 371 | { |
372 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 372 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
373 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 373 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -426,7 +426,7 @@ static int omap_wdt_resume(struct platform_device *pdev) | |||
426 | 426 | ||
427 | static struct platform_driver omap_wdt_driver = { | 427 | static struct platform_driver omap_wdt_driver = { |
428 | .probe = omap_wdt_probe, | 428 | .probe = omap_wdt_probe, |
429 | .remove = omap_wdt_remove, | 429 | .remove = __devexit_p(omap_wdt_remove), |
430 | .shutdown = omap_wdt_shutdown, | 430 | .shutdown = omap_wdt_shutdown, |
431 | .suspend = omap_wdt_suspend, | 431 | .suspend = omap_wdt_suspend, |
432 | .resume = omap_wdt_resume, | 432 | .resume = omap_wdt_resume, |
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index e81441f103dd..7529616739d2 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c | |||
@@ -42,7 +42,17 @@ static unsigned int wdt_tclk; | |||
42 | static unsigned long wdt_status; | 42 | static unsigned long wdt_status; |
43 | static spinlock_t wdt_lock; | 43 | static spinlock_t wdt_lock; |
44 | 44 | ||
45 | static void wdt_enable(void) | 45 | static void orion5x_wdt_ping(void) |
46 | { | ||
47 | spin_lock(&wdt_lock); | ||
48 | |||
49 | /* Reload watchdog duration */ | ||
50 | writel(wdt_tclk * heartbeat, WDT_VAL); | ||
51 | |||
52 | spin_unlock(&wdt_lock); | ||
53 | } | ||
54 | |||
55 | static void orion5x_wdt_enable(void) | ||
46 | { | 56 | { |
47 | u32 reg; | 57 | u32 reg; |
48 | 58 | ||
@@ -69,7 +79,7 @@ static void wdt_enable(void) | |||
69 | spin_unlock(&wdt_lock); | 79 | spin_unlock(&wdt_lock); |
70 | } | 80 | } |
71 | 81 | ||
72 | static void wdt_disable(void) | 82 | static void orion5x_wdt_disable(void) |
73 | { | 83 | { |
74 | u32 reg; | 84 | u32 reg; |
75 | 85 | ||
@@ -101,7 +111,7 @@ static int orion5x_wdt_open(struct inode *inode, struct file *file) | |||
101 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 111 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
102 | return -EBUSY; | 112 | return -EBUSY; |
103 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 113 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
104 | wdt_enable(); | 114 | orion5x_wdt_enable(); |
105 | return nonseekable_open(inode, file); | 115 | return nonseekable_open(inode, file); |
106 | } | 116 | } |
107 | 117 | ||
@@ -122,18 +132,28 @@ static ssize_t orion5x_wdt_write(struct file *file, const char *data, | |||
122 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | 132 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); |
123 | } | 133 | } |
124 | } | 134 | } |
125 | wdt_enable(); | 135 | orion5x_wdt_ping(); |
126 | } | 136 | } |
127 | return len; | 137 | return len; |
128 | } | 138 | } |
129 | 139 | ||
130 | static struct watchdog_info ident = { | 140 | static int orion5x_wdt_settimeout(int new_time) |
141 | { | ||
142 | if ((new_time <= 0) || (new_time > wdt_max_duration)) | ||
143 | return -EINVAL; | ||
144 | |||
145 | /* Set new watchdog time to be used when | ||
146 | * orion5x_wdt_enable() or orion5x_wdt_ping() is called. */ | ||
147 | heartbeat = new_time; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static const struct watchdog_info ident = { | ||
131 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 152 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | |
132 | WDIOF_KEEPALIVEPING, | 153 | WDIOF_KEEPALIVEPING, |
133 | .identity = "Orion5x Watchdog", | 154 | .identity = "Orion5x Watchdog", |
134 | }; | 155 | }; |
135 | 156 | ||
136 | |||
137 | static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | 157 | static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, |
138 | unsigned long arg) | 158 | unsigned long arg) |
139 | { | 159 | { |
@@ -152,7 +172,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
152 | break; | 172 | break; |
153 | 173 | ||
154 | case WDIOC_KEEPALIVE: | 174 | case WDIOC_KEEPALIVE: |
155 | wdt_enable(); | 175 | orion5x_wdt_ping(); |
156 | ret = 0; | 176 | ret = 0; |
157 | break; | 177 | break; |
158 | 178 | ||
@@ -161,12 +181,11 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
161 | if (ret) | 181 | if (ret) |
162 | break; | 182 | break; |
163 | 183 | ||
164 | if (time <= 0 || time > wdt_max_duration) { | 184 | if (orion5x_wdt_settimeout(time)) { |
165 | ret = -EINVAL; | 185 | ret = -EINVAL; |
166 | break; | 186 | break; |
167 | } | 187 | } |
168 | heartbeat = time; | 188 | orion5x_wdt_ping(); |
169 | wdt_enable(); | ||
170 | /* Fall through */ | 189 | /* Fall through */ |
171 | 190 | ||
172 | case WDIOC_GETTIMEOUT: | 191 | case WDIOC_GETTIMEOUT: |
@@ -187,7 +206,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
187 | static int orion5x_wdt_release(struct inode *inode, struct file *file) | 206 | static int orion5x_wdt_release(struct inode *inode, struct file *file) |
188 | { | 207 | { |
189 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | 208 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
190 | wdt_disable(); | 209 | orion5x_wdt_disable(); |
191 | else | 210 | else |
192 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 211 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
193 | "timer will not stop\n"); | 212 | "timer will not stop\n"); |
@@ -230,7 +249,7 @@ static int __devinit orion5x_wdt_probe(struct platform_device *pdev) | |||
230 | orion5x_wdt_miscdev.parent = &pdev->dev; | 249 | orion5x_wdt_miscdev.parent = &pdev->dev; |
231 | 250 | ||
232 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; | 251 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; |
233 | if (heartbeat <= 0 || heartbeat > wdt_max_duration) | 252 | if (orion5x_wdt_settimeout(heartbeat)) |
234 | heartbeat = wdt_max_duration; | 253 | heartbeat = wdt_max_duration; |
235 | 254 | ||
236 | ret = misc_register(&orion5x_wdt_miscdev); | 255 | ret = misc_register(&orion5x_wdt_miscdev); |
@@ -247,7 +266,7 @@ static int __devexit orion5x_wdt_remove(struct platform_device *pdev) | |||
247 | int ret; | 266 | int ret; |
248 | 267 | ||
249 | if (test_bit(WDT_IN_USE, &wdt_status)) { | 268 | if (test_bit(WDT_IN_USE, &wdt_status)) { |
250 | wdt_disable(); | 269 | orion5x_wdt_disable(); |
251 | clear_bit(WDT_IN_USE, &wdt_status); | 270 | clear_bit(WDT_IN_USE, &wdt_status); |
252 | } | 271 | } |
253 | 272 | ||
@@ -258,9 +277,16 @@ static int __devexit orion5x_wdt_remove(struct platform_device *pdev) | |||
258 | return ret; | 277 | return ret; |
259 | } | 278 | } |
260 | 279 | ||
280 | static void orion5x_wdt_shutdown(struct platform_device *pdev) | ||
281 | { | ||
282 | if (test_bit(WDT_IN_USE, &wdt_status)) | ||
283 | orion5x_wdt_disable(); | ||
284 | } | ||
285 | |||
261 | static struct platform_driver orion5x_wdt_driver = { | 286 | static struct platform_driver orion5x_wdt_driver = { |
262 | .probe = orion5x_wdt_probe, | 287 | .probe = orion5x_wdt_probe, |
263 | .remove = __devexit_p(orion5x_wdt_remove), | 288 | .remove = __devexit_p(orion5x_wdt_remove), |
289 | .shutdown = orion5x_wdt_shutdown, | ||
264 | .driver = { | 290 | .driver = { |
265 | .owner = THIS_MODULE, | 291 | .owner = THIS_MODULE, |
266 | .name = "orion5x_wdt", | 292 | .name = "orion5x_wdt", |
@@ -285,10 +311,11 @@ MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); | |||
285 | MODULE_DESCRIPTION("Orion5x Processor Watchdog"); | 311 | MODULE_DESCRIPTION("Orion5x Processor Watchdog"); |
286 | 312 | ||
287 | module_param(heartbeat, int, 0); | 313 | module_param(heartbeat, int, 0); |
288 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds"); | 314 | MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); |
289 | 315 | ||
290 | module_param(nowayout, int, 0); | 316 | module_param(nowayout, int, 0); |
291 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | 317 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
318 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
292 | 319 | ||
293 | MODULE_LICENSE("GPL"); | 320 | MODULE_LICENSE("GPL"); |
294 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 321 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |