diff options
Diffstat (limited to 'drivers')
212 files changed, 10360 insertions, 862 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a603bbf9b1b..66e012cd327 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -582,18 +582,18 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
| 582 | { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */ | 582 | { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */ |
| 583 | { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */ | 583 | { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */ |
| 584 | { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */ | 584 | { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */ |
| 585 | { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */ | 585 | { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */ |
| 586 | { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */ | 586 | { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */ |
| 587 | { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */ | 587 | { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */ |
| 588 | { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */ | 588 | { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */ |
| 589 | { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */ | 589 | { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */ |
| 590 | { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ | 590 | { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */ |
| 591 | { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ | 591 | { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */ |
| 592 | { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ | 592 | { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */ |
| 593 | { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */ | 593 | { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */ |
| 594 | { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */ | 594 | { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */ |
| 595 | { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */ | 595 | { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */ |
| 596 | { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ | 596 | { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */ |
| 597 | 597 | ||
| 598 | /* SiS */ | 598 | /* SiS */ |
| 599 | { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ | 599 | { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9fbf0595f3d..060bcd601f5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -1322,14 +1322,16 @@ static u64 ata_id_n_sectors(const u16 *id) | |||
| 1322 | { | 1322 | { |
| 1323 | if (ata_id_has_lba(id)) { | 1323 | if (ata_id_has_lba(id)) { |
| 1324 | if (ata_id_has_lba48(id)) | 1324 | if (ata_id_has_lba48(id)) |
| 1325 | return ata_id_u64(id, 100); | 1325 | return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); |
| 1326 | else | 1326 | else |
| 1327 | return ata_id_u32(id, 60); | 1327 | return ata_id_u32(id, ATA_ID_LBA_CAPACITY); |
| 1328 | } else { | 1328 | } else { |
| 1329 | if (ata_id_current_chs_valid(id)) | 1329 | if (ata_id_current_chs_valid(id)) |
| 1330 | return ata_id_u32(id, 57); | 1330 | return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] * |
| 1331 | id[ATA_ID_CUR_SECTORS]; | ||
| 1331 | else | 1332 | else |
| 1332 | return id[1] * id[3] * id[6]; | 1333 | return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * |
| 1334 | id[ATA_ID_SECTORS]; | ||
| 1333 | } | 1335 | } |
| 1334 | } | 1336 | } |
| 1335 | 1337 | ||
| @@ -4612,7 +4614,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) | |||
| 4612 | VPRINTK("unmapping %u sg elements\n", qc->n_elem); | 4614 | VPRINTK("unmapping %u sg elements\n", qc->n_elem); |
| 4613 | 4615 | ||
| 4614 | if (qc->n_elem) | 4616 | if (qc->n_elem) |
| 4615 | dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); | 4617 | dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir); |
| 4616 | 4618 | ||
| 4617 | qc->flags &= ~ATA_QCFLAG_DMAMAP; | 4619 | qc->flags &= ~ATA_QCFLAG_DMAMAP; |
| 4618 | qc->sg = NULL; | 4620 | qc->sg = NULL; |
| @@ -4727,7 +4729,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) | |||
| 4727 | return -1; | 4729 | return -1; |
| 4728 | 4730 | ||
| 4729 | DPRINTK("%d sg elements mapped\n", n_elem); | 4731 | DPRINTK("%d sg elements mapped\n", n_elem); |
| 4730 | 4732 | qc->orig_n_elem = qc->n_elem; | |
| 4731 | qc->n_elem = n_elem; | 4733 | qc->n_elem = n_elem; |
| 4732 | qc->flags |= ATA_QCFLAG_DMAMAP; | 4734 | qc->flags |= ATA_QCFLAG_DMAMAP; |
| 4733 | 4735 | ||
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ce2ef047533..ea890911d4f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
| @@ -2423,11 +2423,14 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2423 | } | 2423 | } |
| 2424 | 2424 | ||
| 2425 | /* prereset() might have cleared ATA_EH_RESET. If so, | 2425 | /* prereset() might have cleared ATA_EH_RESET. If so, |
| 2426 | * bang classes and return. | 2426 | * bang classes, thaw and return. |
| 2427 | */ | 2427 | */ |
| 2428 | if (reset && !(ehc->i.action & ATA_EH_RESET)) { | 2428 | if (reset && !(ehc->i.action & ATA_EH_RESET)) { |
| 2429 | ata_for_each_dev(dev, link, ALL) | 2429 | ata_for_each_dev(dev, link, ALL) |
| 2430 | classes[dev->devno] = ATA_DEV_NONE; | 2430 | classes[dev->devno] = ATA_DEV_NONE; |
| 2431 | if ((ap->pflags & ATA_PFLAG_FROZEN) && | ||
| 2432 | ata_is_host_link(link)) | ||
| 2433 | ata_eh_thaw_port(ap); | ||
| 2431 | rc = 0; | 2434 | rc = 0; |
| 2432 | goto out; | 2435 | goto out; |
| 2433 | } | 2436 | } |
| @@ -2901,7 +2904,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev) | |||
| 2901 | int i; | 2904 | int i; |
| 2902 | 2905 | ||
| 2903 | for (i = 0; i < ATA_EH_UA_TRIES; i++) { | 2906 | for (i = 0; i < ATA_EH_UA_TRIES; i++) { |
| 2904 | u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; | 2907 | u8 *sense_buffer = dev->link->ap->sector_buf; |
| 2905 | u8 sense_key = 0; | 2908 | u8 sense_key = 0; |
| 2906 | unsigned int err_mask; | 2909 | unsigned int err_mask; |
| 2907 | 2910 | ||
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 63719ab9ea4..115b1cd6dcf 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <linux/libata.h> | 24 | #include <linux/libata.h> |
| 25 | 25 | ||
| 26 | #define DRV_NAME "pata_amd" | 26 | #define DRV_NAME "pata_amd" |
| 27 | #define DRV_VERSION "0.3.11" | 27 | #define DRV_VERSION "0.4.1" |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
| 30 | * timing_setup - shared timing computation and load | 30 | * timing_setup - shared timing computation and load |
| @@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline) | |||
| 145 | return ata_sff_prereset(link, deadline); | 145 | return ata_sff_prereset(link, deadline); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | /** | ||
| 149 | * amd_cable_detect - report cable type | ||
| 150 | * @ap: port | ||
| 151 | * | ||
| 152 | * AMD controller/BIOS setups record the cable type in word 0x42 | ||
| 153 | */ | ||
| 154 | |||
| 148 | static int amd_cable_detect(struct ata_port *ap) | 155 | static int amd_cable_detect(struct ata_port *ap) |
| 149 | { | 156 | { |
| 150 | static const u32 bitmask[2] = {0x03, 0x0C}; | 157 | static const u32 bitmask[2] = {0x03, 0x0C}; |
| @@ -158,6 +165,40 @@ static int amd_cable_detect(struct ata_port *ap) | |||
| 158 | } | 165 | } |
| 159 | 166 | ||
| 160 | /** | 167 | /** |
| 168 | * amd_fifo_setup - set the PIO FIFO for ATA/ATAPI | ||
| 169 | * @ap: ATA interface | ||
| 170 | * @adev: ATA device | ||
| 171 | * | ||
| 172 | * Set the PCI fifo for this device according to the devices present | ||
| 173 | * on the bus at this point in time. We need to turn the post write buffer | ||
| 174 | * off for ATAPI devices as we may need to issue a word sized write to the | ||
| 175 | * device as the final I/O | ||
| 176 | */ | ||
| 177 | |||
| 178 | static void amd_fifo_setup(struct ata_port *ap) | ||
| 179 | { | ||
| 180 | struct ata_device *adev; | ||
| 181 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
| 182 | static const u8 fifobit[2] = { 0xC0, 0x30}; | ||
| 183 | u8 fifo = fifobit[ap->port_no]; | ||
| 184 | u8 r; | ||
| 185 | |||
| 186 | |||
| 187 | ata_for_each_dev(adev, &ap->link, ENABLED) { | ||
| 188 | if (adev->class == ATA_DEV_ATAPI) | ||
| 189 | fifo = 0; | ||
| 190 | } | ||
| 191 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */ | ||
| 192 | fifo = 0; | ||
| 193 | |||
| 194 | /* On the later chips the read prefetch bits become no-op bits */ | ||
| 195 | pci_read_config_byte(pdev, 0x41, &r); | ||
| 196 | r &= ~fifobit[ap->port_no]; | ||
| 197 | r |= fifo; | ||
| 198 | pci_write_config_byte(pdev, 0x41, r); | ||
| 199 | } | ||
| 200 | |||
| 201 | /** | ||
| 161 | * amd33_set_piomode - set initial PIO mode data | 202 | * amd33_set_piomode - set initial PIO mode data |
| 162 | * @ap: ATA interface | 203 | * @ap: ATA interface |
| 163 | * @adev: ATA device | 204 | * @adev: ATA device |
| @@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap) | |||
| 167 | 208 | ||
| 168 | static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev) | 209 | static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev) |
| 169 | { | 210 | { |
| 211 | amd_fifo_setup(ap); | ||
| 170 | timing_setup(ap, adev, 0x40, adev->pio_mode, 1); | 212 | timing_setup(ap, adev, 0x40, adev->pio_mode, 1); |
| 171 | } | 213 | } |
| 172 | 214 | ||
| 173 | static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev) | 215 | static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev) |
| 174 | { | 216 | { |
| 217 | amd_fifo_setup(ap); | ||
| 175 | timing_setup(ap, adev, 0x40, adev->pio_mode, 2); | 218 | timing_setup(ap, adev, 0x40, adev->pio_mode, 2); |
| 176 | } | 219 | } |
| 177 | 220 | ||
| 178 | static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev) | 221 | static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev) |
| 179 | { | 222 | { |
| 223 | amd_fifo_setup(ap); | ||
| 180 | timing_setup(ap, adev, 0x40, adev->pio_mode, 3); | 224 | timing_setup(ap, adev, 0x40, adev->pio_mode, 3); |
| 181 | } | 225 | } |
| 182 | 226 | ||
| 183 | static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev) | 227 | static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev) |
| 184 | { | 228 | { |
| 229 | amd_fifo_setup(ap); | ||
| 185 | timing_setup(ap, adev, 0x40, adev->pio_mode, 4); | 230 | timing_setup(ap, adev, 0x40, adev->pio_mode, 4); |
| 186 | } | 231 | } |
| 187 | 232 | ||
| @@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = { | |||
| 397 | .set_dmamode = nv133_set_dmamode, | 442 | .set_dmamode = nv133_set_dmamode, |
| 398 | }; | 443 | }; |
| 399 | 444 | ||
| 445 | static void amd_clear_fifo(struct pci_dev *pdev) | ||
| 446 | { | ||
| 447 | u8 fifo; | ||
| 448 | /* Disable the FIFO, the FIFO logic will re-enable it as | ||
| 449 | appropriate */ | ||
| 450 | pci_read_config_byte(pdev, 0x41, &fifo); | ||
| 451 | fifo &= 0x0F; | ||
| 452 | pci_write_config_byte(pdev, 0x41, fifo); | ||
| 453 | } | ||
| 454 | |||
| 400 | static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 455 | static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
| 401 | { | 456 | { |
| 402 | static const struct ata_port_info info[10] = { | 457 | static const struct ata_port_info info[10] = { |
| @@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 503 | 558 | ||
| 504 | if (type < 3) | 559 | if (type < 3) |
| 505 | ata_pci_bmdma_clear_simplex(pdev); | 560 | ata_pci_bmdma_clear_simplex(pdev); |
| 506 | 561 | if (pdev->vendor == PCI_VENDOR_ID_AMD) | |
| 507 | /* Check for AMD7411 */ | 562 | amd_clear_fifo(pdev); |
| 508 | if (type == 3) | ||
| 509 | /* FIFO is broken */ | ||
| 510 | pci_write_config_byte(pdev, 0x41, fifo & 0x0F); | ||
| 511 | else | ||
| 512 | pci_write_config_byte(pdev, 0x41, fifo | 0xF0); | ||
| 513 | |||
| 514 | /* Cable detection on Nvidia chips doesn't work too well, | 563 | /* Cable detection on Nvidia chips doesn't work too well, |
| 515 | * cache BIOS programmed UDMA mode. | 564 | * cache BIOS programmed UDMA mode. |
| 516 | */ | 565 | */ |
| @@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev) | |||
| 536 | return rc; | 585 | return rc; |
| 537 | 586 | ||
| 538 | if (pdev->vendor == PCI_VENDOR_ID_AMD) { | 587 | if (pdev->vendor == PCI_VENDOR_ID_AMD) { |
| 539 | u8 fifo; | 588 | amd_clear_fifo(pdev); |
| 540 | pci_read_config_byte(pdev, 0x41, &fifo); | ||
| 541 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) | ||
| 542 | /* FIFO is broken */ | ||
| 543 | pci_write_config_byte(pdev, 0x41, fifo & 0x0F); | ||
| 544 | else | ||
| 545 | pci_write_config_byte(pdev, 0x41, fifo | 0xF0); | ||
| 546 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 || | 589 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 || |
| 547 | pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401) | 590 | pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401) |
| 548 | ata_pci_bmdma_clear_simplex(pdev); | 591 | ata_pci_bmdma_clear_simplex(pdev); |
| 549 | } | 592 | } |
| 550 | |||
| 551 | ata_host_resume(host); | 593 | ata_host_resume(host); |
| 552 | return 0; | 594 | return 0; |
| 553 | } | 595 | } |
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index f1bb2f9fecb..b05b86a912c 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c | |||
| @@ -557,6 +557,9 @@ static unsigned int it821x_read_id(struct ata_device *adev, | |||
| 557 | id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ | 557 | id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ |
| 558 | id[86] |= 0x0400; /* LBA48 on */ | 558 | id[86] |= 0x0400; /* LBA48 on */ |
| 559 | id[ATA_ID_MAJOR_VER] |= 0x1F; | 559 | id[ATA_ID_MAJOR_VER] |= 0x1F; |
| 560 | /* Clear the serial number because it's different each boot | ||
| 561 | which breaks validation on resume */ | ||
| 562 | memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN); | ||
| 560 | } | 563 | } |
| 561 | return err_mask; | 564 | return err_mask; |
| 562 | } | 565 | } |
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 6c1d778b63a..e3bc1b43628 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c | |||
| @@ -283,9 +283,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
| 283 | static unsigned int pdc_data_xfer_vlb(struct ata_device *dev, | 283 | static unsigned int pdc_data_xfer_vlb(struct ata_device *dev, |
| 284 | unsigned char *buf, unsigned int buflen, int rw) | 284 | unsigned char *buf, unsigned int buflen, int rw) |
| 285 | { | 285 | { |
| 286 | if (ata_id_has_dword_io(dev->id)) { | 286 | int slop = buflen & 3; |
| 287 | /* 32bit I/O capable *and* we need to write a whole number of dwords */ | ||
| 288 | if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) { | ||
| 287 | struct ata_port *ap = dev->link->ap; | 289 | struct ata_port *ap = dev->link->ap; |
| 288 | int slop = buflen & 3; | ||
| 289 | unsigned long flags; | 290 | unsigned long flags; |
| 290 | 291 | ||
| 291 | local_irq_save(flags); | 292 | local_irq_save(flags); |
| @@ -735,7 +736,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf, | |||
| 735 | struct ata_port *ap = adev->link->ap; | 736 | struct ata_port *ap = adev->link->ap; |
| 736 | int slop = buflen & 3; | 737 | int slop = buflen & 3; |
| 737 | 738 | ||
| 738 | if (ata_id_has_dword_io(adev->id)) { | 739 | if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) { |
| 739 | if (rw == WRITE) | 740 | if (rw == WRITE) |
| 740 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | 741 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); |
| 741 | else | 742 | else |
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 4ae1a4138b4..7007edd2d45 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
| @@ -3114,19 +3114,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) | |||
| 3114 | writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); | 3114 | writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); |
| 3115 | } | 3115 | } |
| 3116 | 3116 | ||
| 3117 | if (!IS_SOC(hpriv)) { | 3117 | /* Clear any currently outstanding host interrupt conditions */ |
| 3118 | /* Clear any currently outstanding host interrupt conditions */ | 3118 | writelfl(0, mmio + hpriv->irq_cause_ofs); |
| 3119 | writelfl(0, mmio + hpriv->irq_cause_ofs); | ||
| 3120 | 3119 | ||
| 3121 | /* and unmask interrupt generation for host regs */ | 3120 | /* and unmask interrupt generation for host regs */ |
| 3122 | writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); | 3121 | writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); |
| 3123 | 3122 | ||
| 3124 | /* | 3123 | /* |
| 3125 | * enable only global host interrupts for now. | 3124 | * enable only global host interrupts for now. |
| 3126 | * The per-port interrupts get done later as ports are set up. | 3125 | * The per-port interrupts get done later as ports are set up. |
| 3127 | */ | 3126 | */ |
| 3128 | mv_set_main_irq_mask(host, 0, PCI_ERR); | 3127 | mv_set_main_irq_mask(host, 0, PCI_ERR); |
| 3129 | } | ||
| 3130 | done: | 3128 | done: |
| 3131 | return rc; | 3129 | return rc; |
| 3132 | } | 3130 | } |
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 55a8eed3f3a..f65b53785a8 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
| @@ -2523,7 +2523,7 @@ static void __exit nv_exit(void) | |||
| 2523 | module_init(nv_init); | 2523 | module_init(nv_init); |
| 2524 | module_exit(nv_exit); | 2524 | module_exit(nv_exit); |
| 2525 | module_param_named(adma, adma_enabled, bool, 0444); | 2525 | module_param_named(adma, adma_enabled, bool, 0444); |
| 2526 | MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); | 2526 | MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)"); |
| 2527 | module_param_named(swncq, swncq_enabled, bool, 0444); | 2527 | module_param_named(swncq, swncq_enabled, bool, 0444); |
| 2528 | MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)"); | 2528 | MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)"); |
| 2529 | 2529 | ||
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 144a49f1522..8733a2ea04c 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c | |||
| @@ -901,7 +901,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai) | |||
| 901 | clock_l(); udelay(5); | 901 | clock_l(); udelay(5); |
| 902 | for (i = 128; i != 0; i >>= 1) { /* write command out */ | 902 | for (i = 128; i != 0; i >>= 1) { /* write command out */ |
| 903 | tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) | | 903 | tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) | |
| 904 | (data & i) ? CONFIG1_PROMDATA : 0; | 904 | ((data & i) ? CONFIG1_PROMDATA : 0); |
| 905 | if (lanai->conf1 != tmp) { | 905 | if (lanai->conf1 != tmp) { |
| 906 | set_config1(tmp); | 906 | set_config1(tmp); |
| 907 | udelay(5); /* Let new data settle */ | 907 | udelay(5); /* Let new data settle */ |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index d2cb67b6117..4f9b6d79201 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -3606,16 +3606,18 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3606 | if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev)) | 3606 | if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev)) |
| 3607 | return -ENODEV; | 3607 | return -ENODEV; |
| 3608 | 3608 | ||
| 3609 | /* Some devices (notably the HP Smart Array 5i Controller) | 3609 | /* Now try to get the controller to respond to a no-op. Some |
| 3610 | need a little pause here */ | 3610 | devices (notably the HP Smart Array 5i Controller) need |
| 3611 | schedule_timeout_uninterruptible(30*HZ); | 3611 | up to 30 seconds to respond. */ |
| 3612 | 3612 | for (i=0; i<30; i++) { | |
| 3613 | /* Now try to get the controller to respond to a no-op */ | ||
| 3614 | for (i=0; i<12; i++) { | ||
| 3615 | if (cciss_noop(pdev) == 0) | 3613 | if (cciss_noop(pdev) == 0) |
| 3616 | break; | 3614 | break; |
| 3617 | else | 3615 | |
| 3618 | printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : "")); | 3616 | schedule_timeout_uninterruptible(HZ); |
| 3617 | } | ||
| 3618 | if (i == 30) { | ||
| 3619 | printk(KERN_ERR "cciss: controller seems dead\n"); | ||
| 3620 | return -EBUSY; | ||
| 3619 | } | 3621 | } |
| 3620 | } | 3622 | } |
| 3621 | 3623 | ||
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index edbaac6c057..bf034557767 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -392,8 +392,7 @@ lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
| 392 | struct loop_device *lo = p->lo; | 392 | struct loop_device *lo = p->lo; |
| 393 | struct page *page = buf->page; | 393 | struct page *page = buf->page; |
| 394 | sector_t IV; | 394 | sector_t IV; |
| 395 | size_t size; | 395 | int size, ret; |
| 396 | int ret; | ||
| 397 | 396 | ||
| 398 | ret = buf->ops->confirm(pipe, buf); | 397 | ret = buf->ops->confirm(pipe, buf); |
| 399 | if (unlikely(ret)) | 398 | if (unlikely(ret)) |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 918ef725de4..8f905089b72 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/hdreg.h> | 40 | #include <linux/hdreg.h> |
| 41 | #include <linux/cdrom.h> | 41 | #include <linux/cdrom.h> |
| 42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
| 43 | #include <linux/scatterlist.h> | ||
| 43 | 44 | ||
| 44 | #include <xen/xenbus.h> | 45 | #include <xen/xenbus.h> |
| 45 | #include <xen/grant_table.h> | 46 | #include <xen/grant_table.h> |
| @@ -82,6 +83,7 @@ struct blkfront_info | |||
| 82 | enum blkif_state connected; | 83 | enum blkif_state connected; |
| 83 | int ring_ref; | 84 | int ring_ref; |
| 84 | struct blkif_front_ring ring; | 85 | struct blkif_front_ring ring; |
| 86 | struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | ||
| 85 | unsigned int evtchn, irq; | 87 | unsigned int evtchn, irq; |
| 86 | struct request_queue *rq; | 88 | struct request_queue *rq; |
| 87 | struct work_struct work; | 89 | struct work_struct work; |
| @@ -204,12 +206,11 @@ static int blkif_queue_request(struct request *req) | |||
| 204 | struct blkfront_info *info = req->rq_disk->private_data; | 206 | struct blkfront_info *info = req->rq_disk->private_data; |
| 205 | unsigned long buffer_mfn; | 207 | unsigned long buffer_mfn; |
| 206 | struct blkif_request *ring_req; | 208 | struct blkif_request *ring_req; |
| 207 | struct req_iterator iter; | ||
| 208 | struct bio_vec *bvec; | ||
| 209 | unsigned long id; | 209 | unsigned long id; |
| 210 | unsigned int fsect, lsect; | 210 | unsigned int fsect, lsect; |
| 211 | int ref; | 211 | int i, ref; |
| 212 | grant_ref_t gref_head; | 212 | grant_ref_t gref_head; |
| 213 | struct scatterlist *sg; | ||
| 213 | 214 | ||
| 214 | if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) | 215 | if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) |
| 215 | return 1; | 216 | return 1; |
| @@ -238,12 +239,13 @@ static int blkif_queue_request(struct request *req) | |||
| 238 | if (blk_barrier_rq(req)) | 239 | if (blk_barrier_rq(req)) |
| 239 | ring_req->operation = BLKIF_OP_WRITE_BARRIER; | 240 | ring_req->operation = BLKIF_OP_WRITE_BARRIER; |
| 240 | 241 | ||
| 241 | ring_req->nr_segments = 0; | 242 | ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); |
| 242 | rq_for_each_segment(bvec, req, iter) { | 243 | BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST); |
| 243 | BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); | 244 | |
| 244 | buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); | 245 | for_each_sg(info->sg, sg, ring_req->nr_segments, i) { |
| 245 | fsect = bvec->bv_offset >> 9; | 246 | buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg))); |
| 246 | lsect = fsect + (bvec->bv_len >> 9) - 1; | 247 | fsect = sg->offset >> 9; |
| 248 | lsect = fsect + (sg->length >> 9) - 1; | ||
| 247 | /* install a grant reference. */ | 249 | /* install a grant reference. */ |
| 248 | ref = gnttab_claim_grant_reference(&gref_head); | 250 | ref = gnttab_claim_grant_reference(&gref_head); |
| 249 | BUG_ON(ref == -ENOSPC); | 251 | BUG_ON(ref == -ENOSPC); |
| @@ -254,16 +256,12 @@ static int blkif_queue_request(struct request *req) | |||
| 254 | buffer_mfn, | 256 | buffer_mfn, |
| 255 | rq_data_dir(req) ); | 257 | rq_data_dir(req) ); |
| 256 | 258 | ||
| 257 | info->shadow[id].frame[ring_req->nr_segments] = | 259 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); |
| 258 | mfn_to_pfn(buffer_mfn); | 260 | ring_req->seg[i] = |
| 259 | |||
| 260 | ring_req->seg[ring_req->nr_segments] = | ||
| 261 | (struct blkif_request_segment) { | 261 | (struct blkif_request_segment) { |
| 262 | .gref = ref, | 262 | .gref = ref, |
| 263 | .first_sect = fsect, | 263 | .first_sect = fsect, |
| 264 | .last_sect = lsect }; | 264 | .last_sect = lsect }; |
| 265 | |||
| 266 | ring_req->nr_segments++; | ||
| 267 | } | 265 | } |
| 268 | 266 | ||
| 269 | info->ring.req_prod_pvt++; | 267 | info->ring.req_prod_pvt++; |
| @@ -622,6 +620,8 @@ static int setup_blkring(struct xenbus_device *dev, | |||
| 622 | SHARED_RING_INIT(sring); | 620 | SHARED_RING_INIT(sring); |
| 623 | FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); | 621 | FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); |
| 624 | 622 | ||
| 623 | sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); | ||
| 624 | |||
| 625 | err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); | 625 | err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); |
| 626 | if (err < 0) { | 626 | if (err < 0) { |
| 627 | free_page((unsigned long)sring); | 627 | free_page((unsigned long)sring); |
| @@ -977,6 +977,8 @@ static void backend_changed(struct xenbus_device *dev, | |||
| 977 | break; | 977 | break; |
| 978 | 978 | ||
| 979 | case XenbusStateClosing: | 979 | case XenbusStateClosing: |
| 980 | if (info->gd == NULL) | ||
| 981 | xenbus_dev_fatal(dev, -ENODEV, "gd is NULL"); | ||
| 980 | bd = bdget_disk(info->gd, 0); | 982 | bd = bdget_disk(info->gd, 0); |
| 981 | if (bd == NULL) | 983 | if (bd == NULL) |
| 982 | xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); | 984 | xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); |
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 2d637e0fbc0..d9e751be8c5 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c | |||
| @@ -457,10 +457,12 @@ static int init_ixp_crypto(void) | |||
| 457 | if (!ctx_pool) { | 457 | if (!ctx_pool) { |
| 458 | goto err; | 458 | goto err; |
| 459 | } | 459 | } |
| 460 | ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0); | 460 | ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0, |
| 461 | "ixp_crypto:out", NULL); | ||
| 461 | if (ret) | 462 | if (ret) |
| 462 | goto err; | 463 | goto err; |
| 463 | ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0); | 464 | ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0, |
| 465 | "ixp_crypto:in", NULL); | ||
| 464 | if (ret) { | 466 | if (ret) { |
| 465 | qmgr_release_queue(SEND_QID); | 467 | qmgr_release_queue(SEND_QID); |
| 466 | goto err; | 468 | goto err; |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 856b3cc2558..3f0fdd18255 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
| @@ -489,4 +489,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); | |||
| 489 | MODULE_LICENSE("GPL"); | 489 | MODULE_LICENSE("GPL"); |
| 490 | MODULE_AUTHOR("Michal Ludvig"); | 490 | MODULE_AUTHOR("Michal Ludvig"); |
| 491 | 491 | ||
| 492 | MODULE_ALIAS("aes"); | 492 | MODULE_ALIAS("aes-all"); |
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index a7fbadebf62..a2c8e8514b6 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
| @@ -304,7 +304,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); | |||
| 304 | MODULE_LICENSE("GPL"); | 304 | MODULE_LICENSE("GPL"); |
| 305 | MODULE_AUTHOR("Michal Ludvig"); | 305 | MODULE_AUTHOR("Michal Ludvig"); |
| 306 | 306 | ||
| 307 | MODULE_ALIAS("sha1"); | 307 | MODULE_ALIAS("sha1-all"); |
| 308 | MODULE_ALIAS("sha256"); | 308 | MODULE_ALIAS("sha256-all"); |
| 309 | MODULE_ALIAS("sha1-padlock"); | 309 | MODULE_ALIAS("sha1-padlock"); |
| 310 | MODULE_ALIAS("sha256-padlock"); | 310 | MODULE_ALIAS("sha256-padlock"); |
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 33bd7534751..25b743abfb5 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright(c) 2007 Intel Corporation. All rights reserved. | 2 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 732fa1ec36a..e190d8b3070 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
| @@ -430,13 +430,15 @@ late_initcall(dmatest_init); | |||
| 430 | static void __exit dmatest_exit(void) | 430 | static void __exit dmatest_exit(void) |
| 431 | { | 431 | { |
| 432 | struct dmatest_chan *dtc, *_dtc; | 432 | struct dmatest_chan *dtc, *_dtc; |
| 433 | struct dma_chan *chan; | ||
| 433 | 434 | ||
| 434 | list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { | 435 | list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { |
| 435 | list_del(&dtc->node); | 436 | list_del(&dtc->node); |
| 437 | chan = dtc->chan; | ||
| 436 | dmatest_cleanup_channel(dtc); | 438 | dmatest_cleanup_channel(dtc); |
| 437 | pr_debug("dmatest: dropped channel %s\n", | 439 | pr_debug("dmatest: dropped channel %s\n", |
| 438 | dma_chan_name(dtc->chan)); | 440 | dma_chan_name(chan)); |
| 439 | dma_release_channel(dtc->chan); | 441 | dma_release_channel(chan); |
| 440 | } | 442 | } |
| 441 | } | 443 | } |
| 442 | module_exit(dmatest_exit); | 444 | module_exit(dmatest_exit); |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 70126a60623..86d6da47f55 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
| @@ -158,7 +158,8 @@ static void dma_start(struct fsl_dma_chan *fsl_chan) | |||
| 158 | 158 | ||
| 159 | static void dma_halt(struct fsl_dma_chan *fsl_chan) | 159 | static void dma_halt(struct fsl_dma_chan *fsl_chan) |
| 160 | { | 160 | { |
| 161 | int i = 0; | 161 | int i; |
| 162 | |||
| 162 | DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, | 163 | DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, |
| 163 | DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA, | 164 | DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA, |
| 164 | 32); | 165 | 32); |
| @@ -166,8 +167,11 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan) | |||
| 166 | DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS | 167 | DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS |
| 167 | | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32); | 168 | | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32); |
| 168 | 169 | ||
| 169 | while (!dma_is_idle(fsl_chan) && (i++ < 100)) | 170 | for (i = 0; i < 100; i++) { |
| 171 | if (dma_is_idle(fsl_chan)) | ||
| 172 | break; | ||
| 170 | udelay(10); | 173 | udelay(10); |
| 174 | } | ||
| 171 | if (i >= 100 && !dma_is_idle(fsl_chan)) | 175 | if (i >= 100 && !dma_is_idle(fsl_chan)) |
| 172 | dev_err(fsl_chan->dev, "DMA halt timeout!\n"); | 176 | dev_err(fsl_chan->dev, "DMA halt timeout!\n"); |
| 173 | } | 177 | } |
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index 4105d6575b6..ed83dd9df19 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Intel I/OAT DMA Linux driver | 2 | * Intel I/OAT DMA Linux driver |
| 3 | * Copyright(c) 2007 Intel Corporation. | 3 | * Copyright(c) 2007 - 2009 Intel Corporation. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms and conditions of the GNU General Public License, | 6 | * under the terms and conditions of the GNU General Public License, |
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index 6cf622da028..c012a1e1504 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Intel I/OAT DMA Linux driver | 2 | * Intel I/OAT DMA Linux driver |
| 3 | * Copyright(c) 2007 Intel Corporation. | 3 | * Copyright(c) 2007 - 2009 Intel Corporation. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms and conditions of the GNU General Public License, | 6 | * under the terms and conditions of the GNU General Public License, |
| @@ -49,6 +49,23 @@ | |||
| 49 | 49 | ||
| 50 | #define DCA_TAG_MAP_MASK 0xDF | 50 | #define DCA_TAG_MAP_MASK 0xDF |
| 51 | 51 | ||
| 52 | /* expected tag map bytes for I/OAT ver.2 */ | ||
| 53 | #define DCA2_TAG_MAP_BYTE0 0x80 | ||
| 54 | #define DCA2_TAG_MAP_BYTE1 0x0 | ||
| 55 | #define DCA2_TAG_MAP_BYTE2 0x81 | ||
| 56 | #define DCA2_TAG_MAP_BYTE3 0x82 | ||
| 57 | #define DCA2_TAG_MAP_BYTE4 0x82 | ||
| 58 | |||
| 59 | /* verify if tag map matches expected values */ | ||
| 60 | static inline int dca2_tag_map_valid(u8 *tag_map) | ||
| 61 | { | ||
| 62 | return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) && | ||
| 63 | (tag_map[1] == DCA2_TAG_MAP_BYTE1) && | ||
| 64 | (tag_map[2] == DCA2_TAG_MAP_BYTE2) && | ||
| 65 | (tag_map[3] == DCA2_TAG_MAP_BYTE3) && | ||
| 66 | (tag_map[4] == DCA2_TAG_MAP_BYTE4)); | ||
| 67 | } | ||
| 68 | |||
| 52 | /* | 69 | /* |
| 53 | * "Legacy" DCA systems do not implement the DCA register set in the | 70 | * "Legacy" DCA systems do not implement the DCA register set in the |
| 54 | * I/OAT device. Software needs direct support for their tag mappings. | 71 | * I/OAT device. Software needs direct support for their tag mappings. |
| @@ -452,6 +469,13 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase) | |||
| 452 | ioatdca->tag_map[i] = 0; | 469 | ioatdca->tag_map[i] = 0; |
| 453 | } | 470 | } |
| 454 | 471 | ||
| 472 | if (!dca2_tag_map_valid(ioatdca->tag_map)) { | ||
| 473 | dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, " | ||
| 474 | "disabling DCA\n"); | ||
| 475 | free_dca_provider(dca); | ||
| 476 | return NULL; | ||
| 477 | } | ||
| 478 | |||
| 455 | err = register_dca_provider(dca, &pdev->dev); | 479 | err = register_dca_provider(dca, &pdev->dev); |
| 456 | if (err) { | 480 | if (err) { |
| 457 | free_dca_provider(dca); | 481 | free_dca_provider(dca); |
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index b3759c4b653..5905cd36bcd 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Intel I/OAT DMA Linux driver | 2 | * Intel I/OAT DMA Linux driver |
| 3 | * Copyright(c) 2004 - 2007 Intel Corporation. | 3 | * Copyright(c) 2004 - 2009 Intel Corporation. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms and conditions of the GNU General Public License, | 6 | * under the terms and conditions of the GNU General Public License, |
| @@ -189,11 +189,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) | |||
| 189 | ioat_chan->xfercap = xfercap; | 189 | ioat_chan->xfercap = xfercap; |
| 190 | ioat_chan->desccount = 0; | 190 | ioat_chan->desccount = 0; |
| 191 | INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2); | 191 | INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2); |
| 192 | if (ioat_chan->device->version != IOAT_VER_1_2) { | 192 | if (ioat_chan->device->version == IOAT_VER_2_0) |
| 193 | writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE | 193 | writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE | |
| 194 | | IOAT_DMA_DCA_ANY_CPU, | 194 | IOAT_DMA_DCA_ANY_CPU, |
| 195 | ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); | 195 | ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); |
| 196 | } | 196 | else if (ioat_chan->device->version == IOAT_VER_3_0) |
| 197 | writel(IOAT_DMA_DCA_ANY_CPU, | ||
| 198 | ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); | ||
| 197 | spin_lock_init(&ioat_chan->cleanup_lock); | 199 | spin_lock_init(&ioat_chan->cleanup_lock); |
| 198 | spin_lock_init(&ioat_chan->desc_lock); | 200 | spin_lock_init(&ioat_chan->desc_lock); |
| 199 | INIT_LIST_HEAD(&ioat_chan->free_desc); | 201 | INIT_LIST_HEAD(&ioat_chan->free_desc); |
| @@ -1169,9 +1171,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) | |||
| 1169 | * up if the client is done with the descriptor | 1171 | * up if the client is done with the descriptor |
| 1170 | */ | 1172 | */ |
| 1171 | if (async_tx_test_ack(&desc->async_tx)) { | 1173 | if (async_tx_test_ack(&desc->async_tx)) { |
| 1172 | list_del(&desc->node); | 1174 | list_move_tail(&desc->node, |
| 1173 | list_add_tail(&desc->node, | 1175 | &ioat_chan->free_desc); |
| 1174 | &ioat_chan->free_desc); | ||
| 1175 | } else | 1176 | } else |
| 1176 | desc->async_tx.cookie = 0; | 1177 | desc->async_tx.cookie = 0; |
| 1177 | } else { | 1178 | } else { |
| @@ -1362,6 +1363,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
| 1362 | dma_cookie_t cookie; | 1363 | dma_cookie_t cookie; |
| 1363 | int err = 0; | 1364 | int err = 0; |
| 1364 | struct completion cmp; | 1365 | struct completion cmp; |
| 1366 | unsigned long tmo; | ||
| 1365 | 1367 | ||
| 1366 | src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); | 1368 | src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); |
| 1367 | if (!src) | 1369 | if (!src) |
| @@ -1413,9 +1415,10 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
| 1413 | } | 1415 | } |
| 1414 | device->common.device_issue_pending(dma_chan); | 1416 | device->common.device_issue_pending(dma_chan); |
| 1415 | 1417 | ||
| 1416 | wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); | 1418 | tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); |
| 1417 | 1419 | ||
| 1418 | if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) | 1420 | if (tmo == 0 || |
| 1421 | device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) | ||
| 1419 | != DMA_SUCCESS) { | 1422 | != DMA_SUCCESS) { |
| 1420 | dev_err(&device->pdev->dev, | 1423 | dev_err(&device->pdev->dev, |
| 1421 | "Self-test copy timed out, disabling\n"); | 1424 | "Self-test copy timed out, disabling\n"); |
| @@ -1657,6 +1660,13 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, | |||
| 1657 | " %d channels, device version 0x%02x, driver version %s\n", | 1660 | " %d channels, device version 0x%02x, driver version %s\n", |
| 1658 | device->common.chancnt, device->version, IOAT_DMA_VERSION); | 1661 | device->common.chancnt, device->version, IOAT_DMA_VERSION); |
| 1659 | 1662 | ||
| 1663 | if (!device->common.chancnt) { | ||
| 1664 | dev_err(&device->pdev->dev, | ||
| 1665 | "Intel(R) I/OAT DMA Engine problem found: " | ||
| 1666 | "zero channels detected\n"); | ||
| 1667 | goto err_setup_interrupts; | ||
| 1668 | } | ||
| 1669 | |||
| 1660 | err = ioat_dma_setup_interrupts(device); | 1670 | err = ioat_dma_setup_interrupts(device); |
| 1661 | if (err) | 1671 | if (err) |
| 1662 | goto err_setup_interrupts; | 1672 | goto err_setup_interrupts; |
| @@ -1696,6 +1706,9 @@ void ioat_dma_remove(struct ioatdma_device *device) | |||
| 1696 | struct dma_chan *chan, *_chan; | 1706 | struct dma_chan *chan, *_chan; |
| 1697 | struct ioat_dma_chan *ioat_chan; | 1707 | struct ioat_dma_chan *ioat_chan; |
| 1698 | 1708 | ||
| 1709 | if (device->version != IOAT_VER_3_0) | ||
| 1710 | cancel_delayed_work(&device->work); | ||
| 1711 | |||
| 1699 | ioat_dma_remove_interrupts(device); | 1712 | ioat_dma_remove_interrupts(device); |
| 1700 | 1713 | ||
| 1701 | dma_async_device_unregister(&device->common); | 1714 | dma_async_device_unregister(&device->common); |
| @@ -1707,10 +1720,6 @@ void ioat_dma_remove(struct ioatdma_device *device) | |||
| 1707 | pci_release_regions(device->pdev); | 1720 | pci_release_regions(device->pdev); |
| 1708 | pci_disable_device(device->pdev); | 1721 | pci_disable_device(device->pdev); |
| 1709 | 1722 | ||
| 1710 | if (device->version != IOAT_VER_3_0) { | ||
| 1711 | cancel_delayed_work(&device->work); | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | list_for_each_entry_safe(chan, _chan, | 1723 | list_for_each_entry_safe(chan, _chan, |
| 1715 | &device->common.channels, device_node) { | 1724 | &device->common.channels, device_node) { |
| 1716 | ioat_chan = to_ioat_chan(chan); | 1725 | ioat_chan = to_ioat_chan(chan); |
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index a3306d0e137..a52ff4bd460 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. | 2 | * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
| @@ -29,7 +29,7 @@ | |||
| 29 | #include <linux/pci_ids.h> | 29 | #include <linux/pci_ids.h> |
| 30 | #include <net/tcp.h> | 30 | #include <net/tcp.h> |
| 31 | 31 | ||
| 32 | #define IOAT_DMA_VERSION "3.30" | 32 | #define IOAT_DMA_VERSION "3.64" |
| 33 | 33 | ||
| 34 | enum ioat_interrupt { | 34 | enum ioat_interrupt { |
| 35 | none = 0, | 35 | none = 0, |
| @@ -135,12 +135,14 @@ static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev) | |||
| 135 | #ifdef CONFIG_NET_DMA | 135 | #ifdef CONFIG_NET_DMA |
| 136 | switch (dev->version) { | 136 | switch (dev->version) { |
| 137 | case IOAT_VER_1_2: | 137 | case IOAT_VER_1_2: |
| 138 | case IOAT_VER_3_0: | ||
| 139 | sysctl_tcp_dma_copybreak = 4096; | 138 | sysctl_tcp_dma_copybreak = 4096; |
| 140 | break; | 139 | break; |
| 141 | case IOAT_VER_2_0: | 140 | case IOAT_VER_2_0: |
| 142 | sysctl_tcp_dma_copybreak = 2048; | 141 | sysctl_tcp_dma_copybreak = 2048; |
| 143 | break; | 142 | break; |
| 143 | case IOAT_VER_3_0: | ||
| 144 | sysctl_tcp_dma_copybreak = 262144; | ||
| 145 | break; | ||
| 144 | } | 146 | } |
| 145 | #endif | 147 | #endif |
| 146 | } | 148 | } |
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h index f1ae2c776f7..afa57eef86c 100644 --- a/drivers/dma/ioatdma_hw.h +++ b/drivers/dma/ioatdma_hw.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. | 2 | * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h index 827cb503cac..49bc277424f 100644 --- a/drivers/dma/ioatdma_registers.h +++ b/drivers/dma/ioatdma_registers.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. | 2 | * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index ea5440dd10d..16adbe61cfb 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
| @@ -928,19 +928,19 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
| 928 | 928 | ||
| 929 | for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { | 929 | for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { |
| 930 | xor_srcs[src_idx] = alloc_page(GFP_KERNEL); | 930 | xor_srcs[src_idx] = alloc_page(GFP_KERNEL); |
| 931 | if (!xor_srcs[src_idx]) | 931 | if (!xor_srcs[src_idx]) { |
| 932 | while (src_idx--) { | 932 | while (src_idx--) |
| 933 | __free_page(xor_srcs[src_idx]); | 933 | __free_page(xor_srcs[src_idx]); |
| 934 | return -ENOMEM; | 934 | return -ENOMEM; |
| 935 | } | 935 | } |
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | dest = alloc_page(GFP_KERNEL); | 938 | dest = alloc_page(GFP_KERNEL); |
| 939 | if (!dest) | 939 | if (!dest) { |
| 940 | while (src_idx--) { | 940 | while (src_idx--) |
| 941 | __free_page(xor_srcs[src_idx]); | 941 | __free_page(xor_srcs[src_idx]); |
| 942 | return -ENOMEM; | 942 | return -ENOMEM; |
| 943 | } | 943 | } |
| 944 | 944 | ||
| 945 | /* Fill in src buffers */ | 945 | /* Fill in src buffers */ |
| 946 | for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { | 946 | for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { |
| @@ -1401,7 +1401,7 @@ MODULE_ALIAS("platform:iop-adma"); | |||
| 1401 | 1401 | ||
| 1402 | static struct platform_driver iop_adma_driver = { | 1402 | static struct platform_driver iop_adma_driver = { |
| 1403 | .probe = iop_adma_probe, | 1403 | .probe = iop_adma_probe, |
| 1404 | .remove = iop_adma_remove, | 1404 | .remove = __devexit_p(iop_adma_remove), |
| 1405 | .driver = { | 1405 | .driver = { |
| 1406 | .owner = THIS_MODULE, | 1406 | .owner = THIS_MODULE, |
| 1407 | .name = "iop-adma", | 1407 | .name = "iop-adma", |
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 1f154d08e98..ae50a9d1a4e 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c | |||
| @@ -729,7 +729,7 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan, | |||
| 729 | 729 | ||
| 730 | ichan->status = IPU_CHANNEL_READY; | 730 | ichan->status = IPU_CHANNEL_READY; |
| 731 | 731 | ||
| 732 | spin_unlock_irqrestore(ipu->lock, flags); | 732 | spin_unlock_irqrestore(&ipu->lock, flags); |
| 733 | 733 | ||
| 734 | return 0; | 734 | return 0; |
| 735 | } | 735 | } |
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index d35cbd1ff0b..cb7f26fb9f1 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
| @@ -1019,19 +1019,19 @@ mv_xor_xor_self_test(struct mv_xor_device *device) | |||
| 1019 | 1019 | ||
| 1020 | for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { | 1020 | for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { |
| 1021 | xor_srcs[src_idx] = alloc_page(GFP_KERNEL); | 1021 | xor_srcs[src_idx] = alloc_page(GFP_KERNEL); |
| 1022 | if (!xor_srcs[src_idx]) | 1022 | if (!xor_srcs[src_idx]) { |
| 1023 | while (src_idx--) { | 1023 | while (src_idx--) |
| 1024 | __free_page(xor_srcs[src_idx]); | 1024 | __free_page(xor_srcs[src_idx]); |
| 1025 | return -ENOMEM; | 1025 | return -ENOMEM; |
| 1026 | } | 1026 | } |
| 1027 | } | 1027 | } |
| 1028 | 1028 | ||
| 1029 | dest = alloc_page(GFP_KERNEL); | 1029 | dest = alloc_page(GFP_KERNEL); |
| 1030 | if (!dest) | 1030 | if (!dest) { |
| 1031 | while (src_idx--) { | 1031 | while (src_idx--) |
| 1032 | __free_page(xor_srcs[src_idx]); | 1032 | __free_page(xor_srcs[src_idx]); |
| 1033 | return -ENOMEM; | 1033 | return -ENOMEM; |
| 1034 | } | 1034 | } |
| 1035 | 1035 | ||
| 1036 | /* Fill in src buffers */ | 1036 | /* Fill in src buffers */ |
| 1037 | for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { | 1037 | for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { |
| @@ -1287,7 +1287,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp, | |||
| 1287 | 1287 | ||
| 1288 | static struct platform_driver mv_xor_driver = { | 1288 | static struct platform_driver mv_xor_driver = { |
| 1289 | .probe = mv_xor_probe, | 1289 | .probe = mv_xor_probe, |
| 1290 | .remove = mv_xor_remove, | 1290 | .remove = __devexit_p(mv_xor_remove), |
| 1291 | .driver = { | 1291 | .driver = { |
| 1292 | .owner = THIS_MODULE, | 1292 | .owner = THIS_MODULE, |
| 1293 | .name = MV_XOR_NAME, | 1293 | .name = MV_XOR_NAME, |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 72c667f9bee..12715d3c078 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
| @@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
| 420 | dev->sigdata.lock = NULL; | 420 | dev->sigdata.lock = NULL; |
| 421 | master->lock.hw_lock = NULL; /* SHM removed */ | 421 | master->lock.hw_lock = NULL; /* SHM removed */ |
| 422 | master->lock.file_priv = NULL; | 422 | master->lock.file_priv = NULL; |
| 423 | wake_up_interruptible(&master->lock.lock_queue); | 423 | wake_up_interruptible_all(&master->lock.lock_queue); |
| 424 | } | 424 | } |
| 425 | break; | 425 | break; |
| 426 | case _DRM_AGP: | 426 | case _DRM_AGP: |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 733028b4d45..1c3a8c55714 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev) | |||
| 452 | kfree(modes); | 452 | kfree(modes); |
| 453 | kfree(enabled); | 453 | kfree(enabled); |
| 454 | } | 454 | } |
| 455 | |||
| 456 | /** | ||
| 457 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | ||
| 458 | * @encoder: encoder to test | ||
| 459 | * @crtc: crtc to test | ||
| 460 | * | ||
| 461 | * Return false if @encoder can't be driven by @crtc, true otherwise. | ||
| 462 | */ | ||
| 463 | static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, | ||
| 464 | struct drm_crtc *crtc) | ||
| 465 | { | ||
| 466 | struct drm_device *dev; | ||
| 467 | struct drm_crtc *tmp; | ||
| 468 | int crtc_mask = 1; | ||
| 469 | |||
| 470 | WARN(!crtc, "checking null crtc?"); | ||
| 471 | |||
| 472 | dev = crtc->dev; | ||
| 473 | |||
| 474 | list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { | ||
| 475 | if (tmp == crtc) | ||
| 476 | break; | ||
| 477 | crtc_mask <<= 1; | ||
| 478 | } | ||
| 479 | |||
| 480 | if (encoder->possible_crtcs & crtc_mask) | ||
| 481 | return true; | ||
| 482 | return false; | ||
| 483 | } | ||
| 484 | |||
| 485 | /* | ||
| 486 | * Check the CRTC we're going to map each output to vs. its current | ||
| 487 | * CRTC. If they don't match, we have to disable the output and the CRTC | ||
| 488 | * since the driver will have to re-route things. | ||
| 489 | */ | ||
| 490 | static void | ||
| 491 | drm_crtc_prepare_encoders(struct drm_device *dev) | ||
| 492 | { | ||
| 493 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 494 | struct drm_encoder *encoder; | ||
| 495 | |||
| 496 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 497 | encoder_funcs = encoder->helper_private; | ||
| 498 | /* Disable unused encoders */ | ||
| 499 | if (encoder->crtc == NULL) | ||
| 500 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
| 501 | /* Disable encoders whose CRTC is about to change */ | ||
| 502 | if (encoder_funcs->get_crtc && | ||
| 503 | encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) | ||
| 504 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 455 | /** | 508 | /** |
| 456 | * drm_crtc_set_mode - set a mode | 509 | * drm_crtc_set_mode - set a mode |
| 457 | * @crtc: CRTC to program | 510 | * @crtc: CRTC to program |
| @@ -547,6 +600,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
| 547 | encoder_funcs->prepare(encoder); | 600 | encoder_funcs->prepare(encoder); |
| 548 | } | 601 | } |
| 549 | 602 | ||
| 603 | drm_crtc_prepare_encoders(dev); | ||
| 604 | |||
| 550 | crtc_funcs->prepare(crtc); | 605 | crtc_funcs->prepare(crtc); |
| 551 | 606 | ||
| 552 | /* Set up the DPLL and any encoders state that needs to adjust or depend | 607 | /* Set up the DPLL and any encoders state that needs to adjust or depend |
| @@ -617,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 617 | struct drm_device *dev; | 672 | struct drm_device *dev; |
| 618 | struct drm_crtc **save_crtcs, *new_crtc; | 673 | struct drm_crtc **save_crtcs, *new_crtc; |
| 619 | struct drm_encoder **save_encoders, *new_encoder; | 674 | struct drm_encoder **save_encoders, *new_encoder; |
| 620 | struct drm_framebuffer *old_fb; | 675 | struct drm_framebuffer *old_fb = NULL; |
| 621 | bool save_enabled; | 676 | bool save_enabled; |
| 622 | bool mode_changed = false; | 677 | bool mode_changed = false; |
| 623 | bool fb_changed = false; | 678 | bool fb_changed = false; |
| @@ -668,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 668 | * and then just flip_or_move it */ | 723 | * and then just flip_or_move it */ |
| 669 | if (set->crtc->fb != set->fb) { | 724 | if (set->crtc->fb != set->fb) { |
| 670 | /* If we have no fb then treat it as a full mode set */ | 725 | /* If we have no fb then treat it as a full mode set */ |
| 671 | if (set->crtc->fb == NULL) | 726 | if (set->crtc->fb == NULL) { |
| 727 | DRM_DEBUG("crtc has no fb, full mode set\n"); | ||
| 672 | mode_changed = true; | 728 | mode_changed = true; |
| 673 | else if ((set->fb->bits_per_pixel != | 729 | } else if ((set->fb->bits_per_pixel != |
| 674 | set->crtc->fb->bits_per_pixel) || | 730 | set->crtc->fb->bits_per_pixel) || |
| 675 | set->fb->depth != set->crtc->fb->depth) | 731 | set->fb->depth != set->crtc->fb->depth) |
| 676 | fb_changed = true; | 732 | fb_changed = true; |
| @@ -682,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 682 | fb_changed = true; | 738 | fb_changed = true; |
| 683 | 739 | ||
| 684 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { | 740 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
| 685 | DRM_DEBUG("modes are different\n"); | 741 | DRM_DEBUG("modes are different, full mode set\n"); |
| 686 | drm_mode_debug_printmodeline(&set->crtc->mode); | 742 | drm_mode_debug_printmodeline(&set->crtc->mode); |
| 687 | drm_mode_debug_printmodeline(set->mode); | 743 | drm_mode_debug_printmodeline(set->mode); |
| 688 | mode_changed = true; | 744 | mode_changed = true; |
| @@ -708,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 708 | } | 764 | } |
| 709 | 765 | ||
| 710 | if (new_encoder != connector->encoder) { | 766 | if (new_encoder != connector->encoder) { |
| 767 | DRM_DEBUG("encoder changed, full mode switch\n"); | ||
| 711 | mode_changed = true; | 768 | mode_changed = true; |
| 712 | connector->encoder = new_encoder; | 769 | connector->encoder = new_encoder; |
| 713 | } | 770 | } |
| @@ -734,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 734 | if (set->connectors[ro] == connector) | 791 | if (set->connectors[ro] == connector) |
| 735 | new_crtc = set->crtc; | 792 | new_crtc = set->crtc; |
| 736 | } | 793 | } |
| 794 | |||
| 795 | /* Make sure the new CRTC will work with the encoder */ | ||
| 796 | if (new_crtc && | ||
| 797 | !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { | ||
| 798 | ret = -EINVAL; | ||
| 799 | goto fail_set_mode; | ||
| 800 | } | ||
| 737 | if (new_crtc != connector->encoder->crtc) { | 801 | if (new_crtc != connector->encoder->crtc) { |
| 802 | DRM_DEBUG("crtc changed, full mode switch\n"); | ||
| 738 | mode_changed = true; | 803 | mode_changed = true; |
| 739 | connector->encoder->crtc = new_crtc; | 804 | connector->encoder->crtc = new_crtc; |
| 740 | } | 805 | } |
| 806 | DRM_DEBUG("setting connector %d crtc to %p\n", | ||
| 807 | connector->base.id, new_crtc); | ||
| 741 | } | 808 | } |
| 742 | 809 | ||
| 743 | /* mode_set_base is not a required function */ | 810 | /* mode_set_base is not a required function */ |
| @@ -781,6 +848,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 781 | 848 | ||
| 782 | fail_set_mode: | 849 | fail_set_mode: |
| 783 | set->crtc->enabled = save_enabled; | 850 | set->crtc->enabled = save_enabled; |
| 851 | set->crtc->fb = old_fb; | ||
| 784 | count = 0; | 852 | count = 0; |
| 785 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 853 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 786 | if (!connector->encoder) | 854 | if (!connector->encoder) |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5a4d3244758..a839a28d8ee 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid) | |||
| 125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); | 125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
| 126 | goto bad; | 126 | goto bad; |
| 127 | } | 127 | } |
| 128 | if (edid->revision <= 0 || edid->revision > 3) { | 128 | if (edid->revision > 3) { |
| 129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); | 129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); |
| 130 | goto bad; | 130 | goto bad; |
| 131 | } | 131 | } |
| @@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); | 320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); |
| 321 | 321 | ||
| 322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; | 322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; |
| 323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | | 323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) | |
| 324 | pt->vsync_offset_lo); | 324 | pt->vsync_offset_lo); |
| 325 | mode->vsync_end = mode->vsync_start + | 325 | mode->vsync_end = mode->vsync_start + |
| 326 | ((pt->vsync_pulse_width_hi << 8) | | 326 | ((pt->vsync_pulse_width_hi << 4) | |
| 327 | pt->vsync_pulse_width_lo); | 327 | pt->vsync_pulse_width_lo); |
| 328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); | 328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); |
| 329 | 329 | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 6c020fe5431..f52663ebe01 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -484,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 484 | mutex_lock(&dev->struct_mutex); | 484 | mutex_lock(&dev->struct_mutex); |
| 485 | 485 | ||
| 486 | if (file_priv->is_master) { | 486 | if (file_priv->is_master) { |
| 487 | struct drm_master *master = file_priv->master; | ||
| 487 | struct drm_file *temp; | 488 | struct drm_file *temp; |
| 488 | list_for_each_entry(temp, &dev->filelist, lhead) { | 489 | list_for_each_entry(temp, &dev->filelist, lhead) { |
| 489 | if ((temp->master == file_priv->master) && | 490 | if ((temp->master == file_priv->master) && |
| @@ -491,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 491 | temp->authenticated = 0; | 492 | temp->authenticated = 0; |
| 492 | } | 493 | } |
| 493 | 494 | ||
| 495 | /** | ||
| 496 | * Since the master is disappearing, so is the | ||
| 497 | * possibility to lock. | ||
| 498 | */ | ||
| 499 | |||
| 500 | if (master->lock.hw_lock) { | ||
| 501 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 502 | dev->sigdata.lock = NULL; | ||
| 503 | master->lock.hw_lock = NULL; | ||
| 504 | master->lock.file_priv = NULL; | ||
| 505 | wake_up_interruptible_all(&master->lock.lock_queue); | ||
| 506 | } | ||
| 507 | |||
| 494 | if (file_priv->minor->master == file_priv->master) { | 508 | if (file_priv->minor->master == file_priv->master) { |
| 495 | /* drop the reference held my the minor */ | 509 | /* drop the reference held my the minor */ |
| 496 | drm_master_put(&file_priv->minor->master); | 510 | drm_master_put(&file_priv->minor->master); |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50..93e677a481f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
| 435 | */ | 435 | */ |
| 436 | void drm_vblank_put(struct drm_device *dev, int crtc) | 436 | void drm_vblank_put(struct drm_device *dev, int crtc) |
| 437 | { | 437 | { |
| 438 | BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); | ||
| 439 | |||
| 438 | /* Last user schedules interrupt disable */ | 440 | /* Last user schedules interrupt disable */ |
| 439 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) | 441 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) |
| 440 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); | 442 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); |
| @@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
| 460 | * so that interrupts remain enabled in the interim. | 462 | * so that interrupts remain enabled in the interim. |
| 461 | */ | 463 | */ |
| 462 | if (!dev->vblank_inmodeset[crtc]) { | 464 | if (!dev->vblank_inmodeset[crtc]) { |
| 463 | dev->vblank_inmodeset[crtc] = 1; | 465 | dev->vblank_inmodeset[crtc] = 0x1; |
| 464 | drm_vblank_get(dev, crtc); | 466 | if (drm_vblank_get(dev, crtc) == 0) |
| 467 | dev->vblank_inmodeset[crtc] |= 0x2; | ||
| 465 | } | 468 | } |
| 466 | } | 469 | } |
| 467 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
| @@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
| 473 | if (dev->vblank_inmodeset[crtc]) { | 476 | if (dev->vblank_inmodeset[crtc]) { |
| 474 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 477 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 475 | dev->vblank_disable_allowed = 1; | 478 | dev->vblank_disable_allowed = 1; |
| 476 | dev->vblank_inmodeset[crtc] = 0; | ||
| 477 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 479 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
| 478 | drm_vblank_put(dev, crtc); | 480 | |
| 481 | if (dev->vblank_inmodeset[crtc] & 0x2) | ||
| 482 | drm_vblank_put(dev, crtc); | ||
| 483 | |||
| 484 | dev->vblank_inmodeset[crtc] = 0; | ||
| 479 | } | 485 | } |
| 480 | } | 486 | } |
| 481 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 487 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 46e7b28f070..e2f70a516c3 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 80 | __set_current_state(TASK_INTERRUPTIBLE); | 80 | __set_current_state(TASK_INTERRUPTIBLE); |
| 81 | if (!master->lock.hw_lock) { | 81 | if (!master->lock.hw_lock) { |
| 82 | /* Device has been unregistered */ | 82 | /* Device has been unregistered */ |
| 83 | send_sig(SIGTERM, current, 0); | ||
| 83 | ret = -EINTR; | 84 | ret = -EINTR; |
| 84 | break; | 85 | break; |
| 85 | } | 86 | } |
| @@ -93,7 +94,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 93 | /* Contention */ | 94 | /* Contention */ |
| 94 | schedule(); | 95 | schedule(); |
| 95 | if (signal_pending(current)) { | 96 | if (signal_pending(current)) { |
| 96 | ret = -ERESTARTSYS; | 97 | ret = -EINTR; |
| 97 | break; | 98 | break; |
| 98 | } | 99 | } |
| 99 | } | 100 | } |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 46bb923b097..7c8b15b22bf 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
| @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref) | |||
| 146 | 146 | ||
| 147 | drm_ht_remove(&master->magiclist); | 147 | drm_ht_remove(&master->magiclist); |
| 148 | 148 | ||
| 149 | if (master->lock.hw_lock) { | ||
| 150 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 151 | dev->sigdata.lock = NULL; | ||
| 152 | master->lock.hw_lock = NULL; | ||
| 153 | master->lock.file_priv = NULL; | ||
| 154 | wake_up_interruptible(&master->lock.lock_queue); | ||
| 155 | } | ||
| 156 | |||
| 157 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); | 149 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); |
| 158 | } | 150 | } |
| 159 | 151 | ||
| @@ -176,7 +168,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, | |||
| 176 | file_priv->minor->master != file_priv->master) { | 168 | file_priv->minor->master != file_priv->master) { |
| 177 | mutex_lock(&dev->struct_mutex); | 169 | mutex_lock(&dev->struct_mutex); |
| 178 | file_priv->minor->master = drm_master_get(file_priv->master); | 170 | file_priv->minor->master = drm_master_get(file_priv->master); |
| 179 | mutex_lock(&dev->struct_mutex); | 171 | mutex_unlock(&dev->struct_mutex); |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | return 0; | 174 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2d797ffe813..6dab63bdc4c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 811 | dev_priv->hws_map.flags = 0; | 811 | dev_priv->hws_map.flags = 0; |
| 812 | dev_priv->hws_map.mtrr = 0; | 812 | dev_priv->hws_map.mtrr = 0; |
| 813 | 813 | ||
| 814 | drm_core_ioremap(&dev_priv->hws_map, dev); | 814 | drm_core_ioremap_wc(&dev_priv->hws_map, dev); |
| 815 | if (dev_priv->hws_map.handle == NULL) { | 815 | if (dev_priv->hws_map.handle == NULL) { |
| 816 | i915_dma_cleanup(dev); | 816 | i915_dma_cleanup(dev); |
| 817 | dev_priv->status_gfx_addr = 0; | 817 | dev_priv->status_gfx_addr = 0; |
| @@ -1090,6 +1090,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1090 | dev_priv->mm.gtt_mapping = | 1090 | dev_priv->mm.gtt_mapping = |
| 1091 | io_mapping_create_wc(dev->agp->base, | 1091 | io_mapping_create_wc(dev->agp->base, |
| 1092 | dev->agp->agp_info.aper_size * 1024*1024); | 1092 | dev->agp->agp_info.aper_size * 1024*1024); |
| 1093 | if (dev_priv->mm.gtt_mapping == NULL) { | ||
| 1094 | ret = -EIO; | ||
| 1095 | goto out_rmmap; | ||
| 1096 | } | ||
| 1097 | |||
| 1093 | /* Set up a WC MTRR for non-PAT systems. This is more common than | 1098 | /* Set up a WC MTRR for non-PAT systems. This is more common than |
| 1094 | * one would think, because the kernel disables PAT on first | 1099 | * one would think, because the kernel disables PAT on first |
| 1095 | * generation Core chips because WC PAT gets overridden by a UC | 1100 | * generation Core chips because WC PAT gets overridden by a UC |
| @@ -1122,7 +1127,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1122 | if (!I915_NEED_GFX_HWS(dev)) { | 1127 | if (!I915_NEED_GFX_HWS(dev)) { |
| 1123 | ret = i915_init_phys_hws(dev); | 1128 | ret = i915_init_phys_hws(dev); |
| 1124 | if (ret != 0) | 1129 | if (ret != 0) |
| 1125 | goto out_rmmap; | 1130 | goto out_iomapfree; |
| 1126 | } | 1131 | } |
| 1127 | 1132 | ||
| 1128 | /* On the 945G/GM, the chipset reports the MSI capability on the | 1133 | /* On the 945G/GM, the chipset reports the MSI capability on the |
| @@ -1161,6 +1166,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1161 | 1166 | ||
| 1162 | return 0; | 1167 | return 0; |
| 1163 | 1168 | ||
| 1169 | out_iomapfree: | ||
| 1170 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 1164 | out_rmmap: | 1171 | out_rmmap: |
| 1165 | iounmap(dev_priv->regs); | 1172 | iounmap(dev_priv->regs); |
| 1166 | free_priv: | 1173 | free_priv: |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0692622ee2b..b293ef0bae7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -68,9 +68,11 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 68 | i915_save_state(dev); | 68 | i915_save_state(dev); |
| 69 | 69 | ||
| 70 | /* If KMS is active, we do the leavevt stuff here */ | 70 | /* If KMS is active, we do the leavevt stuff here */ |
| 71 | if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) { | 71 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 72 | dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n"); | 72 | if (i915_gem_idle(dev)) |
| 73 | return -EBUSY; | 73 | dev_err(&dev->pdev->dev, |
| 74 | "GEM idle failed, resume may fail\n"); | ||
| 75 | drm_irq_uninstall(dev); | ||
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | intel_opregion_free(dev); | 78 | intel_opregion_free(dev); |
| @@ -108,6 +110,8 @@ static int i915_resume(struct drm_device *dev) | |||
| 108 | if (ret != 0) | 110 | if (ret != 0) |
| 109 | ret = -1; | 111 | ret = -1; |
| 110 | mutex_unlock(&dev->struct_mutex); | 112 | mutex_unlock(&dev->struct_mutex); |
| 113 | |||
| 114 | drm_irq_install(dev); | ||
| 111 | } | 115 | } |
| 112 | 116 | ||
| 113 | return ret; | 117 | return ret; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 25b337438ca..85685bfd12d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1051,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
| 1051 | drm_i915_private_t *dev_priv = dev->dev_private; | 1051 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 1052 | uint32_t seqno; | 1052 | uint32_t seqno; |
| 1053 | 1053 | ||
| 1054 | if (!dev_priv->hw_status_page) | ||
| 1055 | return; | ||
| 1056 | |||
| 1054 | seqno = i915_get_gem_seqno(dev); | 1057 | seqno = i915_get_gem_seqno(dev); |
| 1055 | 1058 | ||
| 1056 | while (!list_empty(&dev_priv->mm.request_list)) { | 1059 | while (!list_empty(&dev_priv->mm.request_list)) { |
| @@ -3545,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 3545 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 3548 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
| 3546 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | 3549 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; |
| 3547 | 3550 | ||
| 3548 | DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); | 3551 | DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); |
| 3549 | ret = copy_from_user(obj_addr, user_data, args->size); | 3552 | ret = copy_from_user(obj_addr, user_data, args->size); |
| 3550 | if (ret) | 3553 | if (ret) |
| 3551 | return -EFAULT; | 3554 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 548ff2c6643..87b6b603469 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data, | |||
| 383 | drm_i915_irq_emit_t *emit = data; | 383 | drm_i915_irq_emit_t *emit = data; |
| 384 | int result; | 384 | int result; |
| 385 | 385 | ||
| 386 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 387 | |||
| 388 | if (!dev_priv) { | 386 | if (!dev_priv) { |
| 389 | DRM_ERROR("called with no initialization\n"); | 387 | DRM_ERROR("called with no initialization\n"); |
| 390 | return -EINVAL; | 388 | return -EINVAL; |
| 391 | } | 389 | } |
| 390 | |||
| 391 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 392 | |||
| 392 | mutex_lock(&dev->struct_mutex); | 393 | mutex_lock(&dev->struct_mutex); |
| 393 | result = i915_emit_irq(dev); | 394 | result = i915_emit_irq(dev); |
| 394 | mutex_unlock(&dev->struct_mutex); | 395 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 65be30dccc7..fc28e2bbd54 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
| 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; | 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; |
| 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; |
| 113 | 113 | ||
| 114 | /* Some VBTs have bogus h/vtotal values */ | ||
| 115 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
| 116 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
| 117 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
| 118 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
| 119 | |||
| 114 | drm_mode_set_name(panel_fixed_mode); | 120 | drm_mode_set_name(panel_fixed_mode); |
| 115 | 121 | ||
| 116 | dev_priv->vbt_mode = panel_fixed_mode; | 122 | dev_priv->vbt_mode = panel_fixed_mode; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 65b635ce28c..a2834276cb3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -217,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) | |||
| 217 | return false; | 217 | return false; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | #define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0) | 220 | #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) |
| 221 | /** | 221 | /** |
| 222 | * Returns whether the given set of divisors are valid for a given refclk with | 222 | * Returns whether the given set of divisors are valid for a given refclk with |
| 223 | * the given connectors. | 223 | * the given connectors. |
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c index 9fee3ca1734..9aefb5e5864 100644 --- a/drivers/i2c/busses/i2c-acorn.c +++ b/drivers/i2c/busses/i2c-acorn.c | |||
| @@ -79,10 +79,11 @@ static struct i2c_algo_bit_data ioc_data = { | |||
| 79 | .getsda = ioc_getsda, | 79 | .getsda = ioc_getsda, |
| 80 | .getscl = ioc_getscl, | 80 | .getscl = ioc_getscl, |
| 81 | .udelay = 80, | 81 | .udelay = 80, |
| 82 | .timeout = 100 | 82 | .timeout = HZ, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | static struct i2c_adapter ioc_ops = { | 85 | static struct i2c_adapter ioc_ops = { |
| 86 | .nr = 0, | ||
| 86 | .algo_data = &ioc_data, | 87 | .algo_data = &ioc_data, |
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| @@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void) | |||
| 90 | { | 91 | { |
| 91 | force_ones = FORCE_ONES | SCL | SDA; | 92 | force_ones = FORCE_ONES | SCL | SDA; |
| 92 | 93 | ||
| 93 | return i2c_bit_add_bus(&ioc_ops); | 94 | return i2c_bit_add_numbered_bus(&ioc_ops); |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | module_init(i2c_ioc_init); | 97 | module_init(i2c_ioc_init); |
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index edab51973bf..a7c59908c45 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
| @@ -72,7 +72,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) | |||
| 72 | { | 72 | { |
| 73 | int timeout = 500; | 73 | int timeout = 500; |
| 74 | 74 | ||
| 75 | while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF)) | 75 | while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout) |
| 76 | udelay(1); | 76 | udelay(1); |
| 77 | 77 | ||
| 78 | if (!timeout) { | 78 | if (!timeout) { |
| @@ -88,7 +88,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) | |||
| 88 | { | 88 | { |
| 89 | int timeout = 500; | 89 | int timeout = 500; |
| 90 | 90 | ||
| 91 | while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF)) | 91 | while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout) |
| 92 | udelay(1); | 92 | udelay(1); |
| 93 | 93 | ||
| 94 | if (!timeout) { | 94 | if (!timeout) { |
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c index 8e846797048..c016f7a2c5f 100644 --- a/drivers/i2c/busses/i2c-ixp2000.c +++ b/drivers/i2c/busses/i2c-ixp2000.c | |||
| @@ -114,7 +114,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev) | |||
| 114 | drv_data->algo_data.getsda = ixp2000_bit_getsda; | 114 | drv_data->algo_data.getsda = ixp2000_bit_getsda; |
| 115 | drv_data->algo_data.getscl = ixp2000_bit_getscl; | 115 | drv_data->algo_data.getscl = ixp2000_bit_getscl; |
| 116 | drv_data->algo_data.udelay = 6; | 116 | drv_data->algo_data.udelay = 6; |
| 117 | drv_data->algo_data.timeout = 100; | 117 | drv_data->algo_data.timeout = HZ; |
| 118 | 118 | ||
| 119 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, | 119 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, |
| 120 | sizeof(drv_data->adapter.name)); | 120 | sizeof(drv_data->adapter.name)); |
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index eeda276f8f1..7f186bbcb99 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
| @@ -482,7 +482,7 @@ mv64xxx_i2c_map_regs(struct platform_device *pd, | |||
| 482 | return 0; | 482 | return 0; |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | static void __devexit | 485 | static void |
| 486 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) | 486 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) |
| 487 | { | 487 | { |
| 488 | if (drv_data->reg_base) { | 488 | if (drv_data->reg_base) { |
| @@ -577,7 +577,7 @@ mv64xxx_i2c_remove(struct platform_device *dev) | |||
| 577 | 577 | ||
| 578 | static struct platform_driver mv64xxx_i2c_driver = { | 578 | static struct platform_driver mv64xxx_i2c_driver = { |
| 579 | .probe = mv64xxx_i2c_probe, | 579 | .probe = mv64xxx_i2c_probe, |
| 580 | .remove = mv64xxx_i2c_remove, | 580 | .remove = __devexit_p(mv64xxx_i2c_remove), |
| 581 | .driver = { | 581 | .driver = { |
| 582 | .owner = THIS_MODULE, | 582 | .owner = THIS_MODULE, |
| 583 | .name = MV64XXX_I2C_CTLR_NAME, | 583 | .name = MV64XXX_I2C_CTLR_NAME, |
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 6af68146c34..bdb1f7510e9 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
| @@ -644,7 +644,7 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, | |||
| 644 | 644 | ||
| 645 | i2c_pxa_start_message(i2c); | 645 | i2c_pxa_start_message(i2c); |
| 646 | 646 | ||
| 647 | while (timeout-- && i2c->msg_num > 0) { | 647 | while (i2c->msg_num > 0 && --timeout) { |
| 648 | i2c_pxa_handler(0, i2c); | 648 | i2c_pxa_handler(0, i2c); |
| 649 | udelay(10); | 649 | udelay(10); |
| 650 | } | 650 | } |
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c index 162b74a0488..42df0eca43d 100644 --- a/drivers/i2c/busses/scx200_i2c.c +++ b/drivers/i2c/busses/scx200_i2c.c | |||
| @@ -76,7 +76,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = { | |||
| 76 | .getsda = scx200_i2c_getsda, | 76 | .getsda = scx200_i2c_getsda, |
| 77 | .getscl = scx200_i2c_getscl, | 77 | .getscl = scx200_i2c_getscl, |
| 78 | .udelay = 10, | 78 | .udelay = 10, |
| 79 | .timeout = 100, | 79 | .timeout = HZ, |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | static struct i2c_adapter scx200_i2c_ops = { | 82 | static struct i2c_adapter scx200_i2c_ops = { |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b1c9abe24c7..e7d984866de 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -1831,7 +1831,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
| 1831 | case I2C_SMBUS_QUICK: | 1831 | case I2C_SMBUS_QUICK: |
| 1832 | msg[0].len = 0; | 1832 | msg[0].len = 0; |
| 1833 | /* Special case: The read/write field is used as data */ | 1833 | /* Special case: The read/write field is used as data */ |
| 1834 | msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0; | 1834 | msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? |
| 1835 | I2C_M_RD : 0); | ||
| 1835 | num = 1; | 1836 | num = 1; |
| 1836 | break; | 1837 | break; |
| 1837 | case I2C_SMBUS_BYTE: | 1838 | case I2C_SMBUS_BYTE: |
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c171988a9f5..7e13d2df9af 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/i2c.h> | 35 | #include <linux/i2c.h> |
| 36 | #include <linux/i2c-dev.h> | 36 | #include <linux/i2c-dev.h> |
| 37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
| 38 | #include <linux/jiffies.h> | ||
| 38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
| 39 | 40 | ||
| 40 | static struct i2c_driver i2cdev_driver; | 41 | static struct i2c_driver i2cdev_driver; |
| @@ -422,7 +423,10 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 422 | client->adapter->retries = arg; | 423 | client->adapter->retries = arg; |
| 423 | break; | 424 | break; |
| 424 | case I2C_TIMEOUT: | 425 | case I2C_TIMEOUT: |
| 425 | client->adapter->timeout = arg; | 426 | /* For historical reasons, user-space sets the timeout |
| 427 | * value in units of 10 ms. | ||
| 428 | */ | ||
| 429 | client->adapter->timeout = msecs_to_jiffies(arg * 10); | ||
| 426 | break; | 430 | break; |
| 427 | default: | 431 | default: |
| 428 | /* NOTE: returning a fault code here could cause trouble | 432 | /* NOTE: returning a fault code here could cause trouble |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3dad2299d9c..5ea3bfad172 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
| @@ -46,7 +46,7 @@ menuconfig IDE | |||
| 46 | SMART parameters from disk drives. | 46 | SMART parameters from disk drives. |
| 47 | 47 | ||
| 48 | To compile this driver as a module, choose M here: the | 48 | To compile this driver as a module, choose M here: the |
| 49 | module will be called ide. | 49 | module will be called ide-core.ko. |
| 50 | 50 | ||
| 51 | For further information, please read <file:Documentation/ide/ide.txt>. | 51 | For further information, please read <file:Documentation/ide/ide.txt>. |
| 52 | 52 | ||
| @@ -721,6 +721,11 @@ config BLK_DEV_IDE_TX4939 | |||
| 721 | depends on SOC_TX4939 | 721 | depends on SOC_TX4939 |
| 722 | select BLK_DEV_IDEDMA_SFF | 722 | select BLK_DEV_IDEDMA_SFF |
| 723 | 723 | ||
| 724 | config BLK_DEV_IDE_AT91 | ||
| 725 | tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support" | ||
| 726 | depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 | ||
| 727 | select IDE_TIMINGS | ||
| 728 | |||
| 724 | config IDE_ARM | 729 | config IDE_ARM |
| 725 | tristate "ARM IDE support" | 730 | tristate "ARM IDE support" |
| 726 | depends on ARM && (ARCH_RPC || ARCH_SHARK) | 731 | depends on ARM && (ARCH_RPC || ARCH_SHARK) |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0e3d7d5b46..1c326d94aa6 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
| @@ -116,3 +116,4 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o | |||
| 116 | 116 | ||
| 117 | obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o | 117 | obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o |
| 118 | obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o | 118 | obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o |
| 119 | obj-$(CONFIG_BLK_DEV_IDE_AT91) += at91_ide.o | ||
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 69660a431cd..77267c85996 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c | |||
| @@ -166,7 +166,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev) | |||
| 166 | * Check for broken FIFO support. | 166 | * Check for broken FIFO support. |
| 167 | */ | 167 | */ |
| 168 | if (dev->vendor == PCI_VENDOR_ID_AMD && | 168 | if (dev->vendor == PCI_VENDOR_ID_AMD && |
| 169 | dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411) | 169 | dev->device == PCI_DEVICE_ID_AMD_VIPER_7411) |
| 170 | t &= 0x0f; | 170 | t &= 0x0f; |
| 171 | else | 171 | else |
| 172 | t |= 0xf0; | 172 | t |= 0xf0; |
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c new file mode 100644 index 00000000000..1bb50f46388 --- /dev/null +++ b/drivers/ide/at91_ide.c | |||
| @@ -0,0 +1,467 @@ | |||
| 1 | /* | ||
| 2 | * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller | ||
| 3 | * with Compact Flash True IDE logic | ||
| 4 | * | ||
| 5 | * Copyright (c) 2008, 2009 Kelvatek Ltd. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/version.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/clk.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/ide.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | |||
| 31 | #include <mach/board.h> | ||
| 32 | #include <mach/gpio.h> | ||
| 33 | #include <mach/at91sam9263.h> | ||
| 34 | #include <mach/at91sam9_smc.h> | ||
| 35 | #include <mach/at91sam9263_matrix.h> | ||
| 36 | |||
| 37 | #define DRV_NAME "at91_ide" | ||
| 38 | |||
| 39 | #define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args) | ||
| 40 | #define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args) | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Access to IDE device is possible through EBI Static Memory Controller | ||
| 44 | * with Compact Flash logic. For details see EBI and SMC datasheet sections | ||
| 45 | * of any microcontroller from AT91SAM9 family. | ||
| 46 | * | ||
| 47 | * Within SMC chip select address space, lines A[23:21] distinguish Compact | ||
| 48 | * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are: | ||
| 49 | * 0x00c0000 - True IDE | ||
| 50 | * 0x00e0000 - Alternate True IDE (Alt Status Register) | ||
| 51 | * | ||
| 52 | * On True IDE mode Task File and Data Register are mapped at the same address. | ||
| 53 | * To distinguish access between these two different bus data width is used: | ||
| 54 | * 8Bit for Task File, 16Bit for Data I/O. | ||
| 55 | * | ||
| 56 | * After initialization we do 8/16 bit flipping (changes in SMC MODE register) | ||
| 57 | * only inside IDE callback routines which are serialized by IDE layer, | ||
| 58 | * so no additional locking needed. | ||
| 59 | */ | ||
| 60 | |||
| 61 | #define TASK_FILE 0x00c00000 | ||
| 62 | #define ALT_MODE 0x00e00000 | ||
| 63 | #define REGS_SIZE 8 | ||
| 64 | |||
| 65 | #define enter_16bit(cs, mode) do { \ | ||
| 66 | mode = at91_sys_read(AT91_SMC_MODE(cs)); \ | ||
| 67 | at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16); \ | ||
| 68 | } while (0) | ||
| 69 | |||
| 70 | #define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode); | ||
| 71 | |||
| 72 | static void set_smc_timings(const u8 chipselect, const u16 cycle, | ||
| 73 | const u16 setup, const u16 pulse, | ||
| 74 | const u16 data_float, int use_iordy) | ||
| 75 | { | ||
| 76 | unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | | ||
| 77 | AT91_SMC_BAT_SELECT; | ||
| 78 | |||
| 79 | /* disable or enable waiting for IORDY signal */ | ||
| 80 | if (use_iordy) | ||
| 81 | mode |= AT91_SMC_EXNWMODE_READY; | ||
| 82 | |||
| 83 | /* add data float cycles if needed */ | ||
| 84 | if (data_float) | ||
| 85 | mode |= AT91_SMC_TDF_(data_float); | ||
| 86 | |||
| 87 | at91_sys_write(AT91_SMC_MODE(chipselect), mode); | ||
| 88 | |||
| 89 | /* setup timings in SMC */ | ||
| 90 | at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) | | ||
| 91 | AT91_SMC_NCS_WRSETUP_(0) | | ||
| 92 | AT91_SMC_NRDSETUP_(setup) | | ||
| 93 | AT91_SMC_NCS_RDSETUP_(0)); | ||
| 94 | at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) | | ||
| 95 | AT91_SMC_NCS_WRPULSE_(cycle) | | ||
| 96 | AT91_SMC_NRDPULSE_(pulse) | | ||
| 97 | AT91_SMC_NCS_RDPULSE_(cycle)); | ||
| 98 | at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) | | ||
| 99 | AT91_SMC_NRDCYCLE_(cycle)); | ||
| 100 | } | ||
| 101 | |||
| 102 | static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) | ||
| 103 | { | ||
| 104 | u64 tmp = ns; | ||
| 105 | |||
| 106 | tmp *= mck_hz; | ||
| 107 | tmp += 1000*1000*1000 - 1; /* round up */ | ||
| 108 | do_div(tmp, 1000*1000*1000); | ||
| 109 | return (unsigned int) tmp; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void apply_timings(const u8 chipselect, const u8 pio, | ||
| 113 | const struct ide_timing *timing, int use_iordy) | ||
| 114 | { | ||
| 115 | unsigned int t0, t1, t2, t6z; | ||
| 116 | unsigned int cycle, setup, pulse, data_float; | ||
| 117 | unsigned int mck_hz; | ||
| 118 | struct clk *mck; | ||
| 119 | |||
| 120 | /* see table 22 of Compact Flash standard 4.1 for the meaning, | ||
| 121 | * we do not stretch active (t2) time, so setup (t1) + hold time (th) | ||
| 122 | * assure at least minimal recovery (t2i) time */ | ||
| 123 | t0 = timing->cyc8b; | ||
| 124 | t1 = timing->setup; | ||
| 125 | t2 = timing->act8b; | ||
| 126 | t6z = (pio < 5) ? 30 : 20; | ||
| 127 | |||
| 128 | pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z); | ||
| 129 | |||
| 130 | mck = clk_get(NULL, "mck"); | ||
| 131 | BUG_ON(IS_ERR(mck)); | ||
| 132 | mck_hz = clk_get_rate(mck); | ||
| 133 | pdbg("mck_hz=%u\n", mck_hz); | ||
| 134 | |||
| 135 | cycle = calc_mck_cycles(t0, mck_hz); | ||
| 136 | setup = calc_mck_cycles(t1, mck_hz); | ||
| 137 | pulse = calc_mck_cycles(t2, mck_hz); | ||
| 138 | data_float = calc_mck_cycles(t6z, mck_hz); | ||
| 139 | |||
| 140 | pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n", | ||
| 141 | cycle, setup, pulse, data_float); | ||
| 142 | |||
| 143 | set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void at91_ide_input_data(ide_drive_t *drive, struct request *rq, | ||
| 147 | void *buf, unsigned int len) | ||
| 148 | { | ||
| 149 | ide_hwif_t *hwif = drive->hwif; | ||
| 150 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 151 | u8 chipselect = hwif->select_data; | ||
| 152 | unsigned long mode; | ||
| 153 | |||
| 154 | pdbg("cs %u buf %p len %d\n", chipselect, buf, len); | ||
| 155 | |||
| 156 | len++; | ||
| 157 | |||
| 158 | enter_16bit(chipselect, mode); | ||
| 159 | __ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2); | ||
| 160 | leave_16bit(chipselect, mode); | ||
| 161 | } | ||
| 162 | |||
| 163 | static void at91_ide_output_data(ide_drive_t *drive, struct request *rq, | ||
| 164 | void *buf, unsigned int len) | ||
| 165 | { | ||
| 166 | ide_hwif_t *hwif = drive->hwif; | ||
| 167 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 168 | u8 chipselect = hwif->select_data; | ||
| 169 | unsigned long mode; | ||
| 170 | |||
| 171 | pdbg("cs %u buf %p len %d\n", chipselect, buf, len); | ||
| 172 | |||
| 173 | enter_16bit(chipselect, mode); | ||
| 174 | __ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2); | ||
| 175 | leave_16bit(chipselect, mode); | ||
| 176 | } | ||
| 177 | |||
| 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, ide_task_t *task) | ||
| 189 | { | ||
| 190 | ide_hwif_t *hwif = drive->hwif; | ||
| 191 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 192 | struct ide_taskfile *tf = &task->tf; | ||
| 193 | u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
| 194 | |||
| 195 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
| 196 | HIHI = 0xFF; | ||
| 197 | |||
| 198 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) { | ||
| 199 | u16 data = (tf->hob_data << 8) | tf->data; | ||
| 200 | |||
| 201 | at91_ide_output_data(drive, NULL, &data, 2); | ||
| 202 | } | ||
| 203 | |||
| 204 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
| 205 | ide_mm_outb(tf->hob_feature, io_ports->feature_addr); | ||
| 206 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
| 207 | ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
| 208 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
| 209 | ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
| 210 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
| 211 | ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
| 212 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
| 213 | ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
| 214 | |||
| 215 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
| 216 | ide_mm_outb(tf->feature, io_ports->feature_addr); | ||
| 217 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
| 218 | ide_mm_outb(tf->nsect, io_ports->nsect_addr); | ||
| 219 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
| 220 | ide_mm_outb(tf->lbal, io_ports->lbal_addr); | ||
| 221 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
| 222 | ide_mm_outb(tf->lbam, io_ports->lbam_addr); | ||
| 223 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
| 224 | ide_mm_outb(tf->lbah, io_ports->lbah_addr); | ||
| 225 | |||
| 226 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
| 227 | ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); | ||
| 228 | } | ||
| 229 | |||
| 230 | static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
| 231 | { | ||
| 232 | ide_hwif_t *hwif = drive->hwif; | ||
| 233 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 234 | struct ide_taskfile *tf = &task->tf; | ||
| 235 | |||
| 236 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
| 237 | u16 data; | ||
| 238 | |||
| 239 | at91_ide_input_data(drive, NULL, &data, 2); | ||
| 240 | tf->data = data & 0xff; | ||
| 241 | tf->hob_data = (data >> 8) & 0xff; | ||
| 242 | } | ||
| 243 | |||
| 244 | /* be sure we're looking at the low order bits */ | ||
| 245 | ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | ||
| 246 | |||
| 247 | if (task->tf_flags & IDE_TFLAG_IN_FEATURE) | ||
| 248 | tf->feature = ide_mm_inb(io_ports->feature_addr); | ||
| 249 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
| 250 | tf->nsect = ide_mm_inb(io_ports->nsect_addr); | ||
| 251 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
| 252 | tf->lbal = ide_mm_inb(io_ports->lbal_addr); | ||
| 253 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
| 254 | tf->lbam = ide_mm_inb(io_ports->lbam_addr); | ||
| 255 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
| 256 | tf->lbah = ide_mm_inb(io_ports->lbah_addr); | ||
| 257 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
| 258 | tf->device = ide_mm_inb(io_ports->device_addr); | ||
| 259 | |||
| 260 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
| 261 | ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | ||
| 262 | |||
| 263 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
| 264 | tf->hob_feature = ide_mm_inb(io_ports->feature_addr); | ||
| 265 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
| 266 | tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); | ||
| 267 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
| 268 | tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); | ||
| 269 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
| 270 | tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); | ||
| 271 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
| 272 | tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
| 277 | { | ||
| 278 | struct ide_timing *timing; | ||
| 279 | u8 chipselect = drive->hwif->select_data; | ||
| 280 | int use_iordy = 0; | ||
| 281 | |||
| 282 | pdbg("chipselect %u pio %u\n", chipselect, pio); | ||
| 283 | |||
| 284 | timing = ide_timing_find_mode(XFER_PIO_0 + pio); | ||
| 285 | BUG_ON(!timing); | ||
| 286 | |||
| 287 | if ((pio > 2 || ata_id_has_iordy(drive->id)) && | ||
| 288 | !(ata_id_is_cfa(drive->id) && pio > 4)) | ||
| 289 | use_iordy = 1; | ||
| 290 | |||
| 291 | apply_timings(chipselect, pio, timing, use_iordy); | ||
| 292 | } | ||
| 293 | |||
| 294 | static const struct ide_tp_ops at91_ide_tp_ops = { | ||
| 295 | .exec_command = ide_exec_command, | ||
| 296 | .read_status = ide_read_status, | ||
| 297 | .read_altstatus = ide_read_altstatus, | ||
| 298 | .set_irq = ide_set_irq, | ||
| 299 | |||
| 300 | .tf_load = at91_ide_tf_load, | ||
| 301 | .tf_read = at91_ide_tf_read, | ||
| 302 | |||
| 303 | .input_data = at91_ide_input_data, | ||
| 304 | .output_data = at91_ide_output_data, | ||
| 305 | }; | ||
| 306 | |||
| 307 | static const struct ide_port_ops at91_ide_port_ops = { | ||
| 308 | .set_pio_mode = at91_ide_set_pio_mode, | ||
| 309 | }; | ||
| 310 | |||
| 311 | static const struct ide_port_info at91_ide_port_info __initdata = { | ||
| 312 | .port_ops = &at91_ide_port_ops, | ||
| 313 | .tp_ops = &at91_ide_tp_ops, | ||
| 314 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | | ||
| 315 | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, | ||
| 316 | .pio_mask = ATA_PIO5, | ||
| 317 | }; | ||
| 318 | |||
| 319 | /* | ||
| 320 | * If interrupt is delivered through GPIO, IRQ are triggered on falling | ||
| 321 | * and rising edge of signal. Whereas IDE device request interrupt on high | ||
| 322 | * level (rising edge in our case). This mean we have fake interrupts, so | ||
| 323 | * we need to check interrupt pin and exit instantly from ISR when line | ||
| 324 | * is on low level. | ||
| 325 | */ | ||
| 326 | |||
| 327 | irqreturn_t at91_irq_handler(int irq, void *dev_id) | ||
| 328 | { | ||
| 329 | int ntries = 8; | ||
| 330 | int pin_val1, pin_val2; | ||
| 331 | |||
| 332 | /* additional deglitch, line can be noisy in badly designed PCB */ | ||
| 333 | do { | ||
| 334 | pin_val1 = at91_get_gpio_value(irq); | ||
| 335 | pin_val2 = at91_get_gpio_value(irq); | ||
| 336 | } while (pin_val1 != pin_val2 && --ntries > 0); | ||
| 337 | |||
| 338 | if (pin_val1 == 0 || ntries <= 0) | ||
| 339 | return IRQ_HANDLED; | ||
| 340 | |||
| 341 | return ide_intr(irq, dev_id); | ||
| 342 | } | ||
| 343 | |||
| 344 | static int __init at91_ide_probe(struct platform_device *pdev) | ||
| 345 | { | ||
| 346 | int ret; | ||
| 347 | hw_regs_t hw; | ||
| 348 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
| 349 | struct ide_host *host; | ||
| 350 | struct resource *res; | ||
| 351 | unsigned long tf_base = 0, ctl_base = 0; | ||
| 352 | struct at91_cf_data *board = pdev->dev.platform_data; | ||
| 353 | |||
| 354 | if (!board) | ||
| 355 | return -ENODEV; | ||
| 356 | |||
| 357 | if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) { | ||
| 358 | perr("no device detected\n"); | ||
| 359 | return -ENODEV; | ||
| 360 | } | ||
| 361 | |||
| 362 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 363 | if (!res) { | ||
| 364 | perr("can't get memory resource\n"); | ||
| 365 | return -ENODEV; | ||
| 366 | } | ||
| 367 | |||
| 368 | if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE, | ||
| 369 | REGS_SIZE, "ide") || | ||
| 370 | !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE, | ||
| 371 | REGS_SIZE, "alt")) { | ||
| 372 | perr("memory resources in use\n"); | ||
| 373 | return -EBUSY; | ||
| 374 | } | ||
| 375 | |||
| 376 | pdbg("chipselect %u irq %u res %08lx\n", board->chipselect, | ||
| 377 | board->irq_pin, (unsigned long) res->start); | ||
| 378 | |||
| 379 | tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE, | ||
| 380 | REGS_SIZE); | ||
| 381 | ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE, | ||
| 382 | REGS_SIZE); | ||
| 383 | if (!tf_base || !ctl_base) { | ||
| 384 | perr("can't map memory regions\n"); | ||
| 385 | return -EBUSY; | ||
| 386 | } | ||
| 387 | |||
| 388 | memset(&hw, 0, sizeof(hw)); | ||
| 389 | |||
| 390 | if (board->flags & AT91_IDE_SWAP_A0_A2) { | ||
| 391 | /* workaround for stupid hardware bug */ | ||
| 392 | hw.io_ports.data_addr = tf_base + 0; | ||
| 393 | hw.io_ports.error_addr = tf_base + 4; | ||
| 394 | hw.io_ports.nsect_addr = tf_base + 2; | ||
| 395 | hw.io_ports.lbal_addr = tf_base + 6; | ||
| 396 | hw.io_ports.lbam_addr = tf_base + 1; | ||
| 397 | hw.io_ports.lbah_addr = tf_base + 5; | ||
| 398 | hw.io_ports.device_addr = tf_base + 3; | ||
| 399 | hw.io_ports.command_addr = tf_base + 7; | ||
| 400 | hw.io_ports.ctl_addr = ctl_base + 3; | ||
| 401 | } else | ||
| 402 | ide_std_init_ports(&hw, tf_base, ctl_base + 6); | ||
| 403 | |||
| 404 | hw.irq = board->irq_pin; | ||
| 405 | hw.chipset = ide_generic; | ||
| 406 | hw.dev = &pdev->dev; | ||
| 407 | |||
| 408 | host = ide_host_alloc(&at91_ide_port_info, hws); | ||
| 409 | if (!host) { | ||
| 410 | perr("failed to allocate ide host\n"); | ||
| 411 | return -ENOMEM; | ||
| 412 | } | ||
| 413 | |||
| 414 | /* setup Static Memory Controller - PIO 0 as default */ | ||
| 415 | apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0); | ||
| 416 | |||
| 417 | /* with GPIO interrupt we have to do quirks in handler */ | ||
| 418 | if (board->irq_pin >= PIN_BASE) | ||
| 419 | host->irq_handler = at91_irq_handler; | ||
| 420 | |||
| 421 | host->ports[0]->select_data = board->chipselect; | ||
| 422 | |||
| 423 | ret = ide_host_register(host, &at91_ide_port_info, hws); | ||
| 424 | if (ret) { | ||
| 425 | perr("failed to register ide host\n"); | ||
| 426 | goto err_free_host; | ||
| 427 | } | ||
| 428 | platform_set_drvdata(pdev, host); | ||
| 429 | return 0; | ||
| 430 | |||
| 431 | err_free_host: | ||
| 432 | ide_host_free(host); | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 436 | static int __exit at91_ide_remove(struct platform_device *pdev) | ||
| 437 | { | ||
| 438 | struct ide_host *host = platform_get_drvdata(pdev); | ||
| 439 | |||
| 440 | ide_host_remove(host); | ||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | static struct platform_driver at91_ide_driver = { | ||
| 445 | .driver = { | ||
| 446 | .name = DRV_NAME, | ||
| 447 | .owner = THIS_MODULE, | ||
| 448 | }, | ||
| 449 | .remove = __exit_p(at91_ide_remove), | ||
| 450 | }; | ||
| 451 | |||
| 452 | static int __init at91_ide_init(void) | ||
| 453 | { | ||
| 454 | return platform_driver_probe(&at91_ide_driver, at91_ide_probe); | ||
| 455 | } | ||
| 456 | |||
| 457 | static void __exit at91_ide_exit(void) | ||
| 458 | { | ||
| 459 | platform_driver_unregister(&at91_ide_driver); | ||
| 460 | } | ||
| 461 | |||
| 462 | module_init(at91_ide_init); | ||
| 463 | module_exit(at91_ide_exit); | ||
| 464 | |||
| 465 | MODULE_LICENSE("GPL"); | ||
| 466 | MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>"); | ||
| 467 | |||
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c index b2735d28f5c..ecd1e62ca91 100644 --- a/drivers/ide/atiixp.c +++ b/drivers/ide/atiixp.c | |||
| @@ -52,7 +52,7 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
| 52 | { | 52 | { |
| 53 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | 53 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); |
| 54 | unsigned long flags; | 54 | unsigned long flags; |
| 55 | int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; | 55 | int timing_shift = (drive->dn ^ 1) * 8; |
| 56 | u32 pio_timing_data; | 56 | u32 pio_timing_data; |
| 57 | u16 pio_mode_data; | 57 | u16 pio_mode_data; |
| 58 | 58 | ||
| @@ -85,7 +85,7 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
| 85 | { | 85 | { |
| 86 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | 86 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); |
| 87 | unsigned long flags; | 87 | unsigned long flags; |
| 88 | int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; | 88 | int timing_shift = (drive->dn ^ 1) * 8; |
| 89 | u32 tmp32; | 89 | u32 tmp32; |
| 90 | u16 tmp16; | 90 | u16 tmp16; |
| 91 | u16 udma_ctl = 0; | 91 | u16 udma_ctl = 0; |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 0bfeb0c79d6..ddfbea41d29 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -55,7 +55,7 @@ | |||
| 55 | 55 | ||
| 56 | static DEFINE_MUTEX(idecd_ref_mutex); | 56 | static DEFINE_MUTEX(idecd_ref_mutex); |
| 57 | 57 | ||
| 58 | static void ide_cd_release(struct kref *); | 58 | static void ide_cd_release(struct device *); |
| 59 | 59 | ||
| 60 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) | 60 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) |
| 61 | { | 61 | { |
| @@ -67,7 +67,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk) | |||
| 67 | if (ide_device_get(cd->drive)) | 67 | if (ide_device_get(cd->drive)) |
| 68 | cd = NULL; | 68 | cd = NULL; |
| 69 | else | 69 | else |
| 70 | kref_get(&cd->kref); | 70 | get_device(&cd->dev); |
| 71 | 71 | ||
| 72 | } | 72 | } |
| 73 | mutex_unlock(&idecd_ref_mutex); | 73 | mutex_unlock(&idecd_ref_mutex); |
| @@ -79,7 +79,7 @@ static void ide_cd_put(struct cdrom_info *cd) | |||
| 79 | ide_drive_t *drive = cd->drive; | 79 | ide_drive_t *drive = cd->drive; |
| 80 | 80 | ||
| 81 | mutex_lock(&idecd_ref_mutex); | 81 | mutex_lock(&idecd_ref_mutex); |
| 82 | kref_put(&cd->kref, ide_cd_release); | 82 | put_device(&cd->dev); |
| 83 | ide_device_put(drive); | 83 | ide_device_put(drive); |
| 84 | mutex_unlock(&idecd_ref_mutex); | 84 | mutex_unlock(&idecd_ref_mutex); |
| 85 | } | 85 | } |
| @@ -194,6 +194,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, | |||
| 194 | bio_sectors = max(bio_sectors(failed_command->bio), 4U); | 194 | bio_sectors = max(bio_sectors(failed_command->bio), 4U); |
| 195 | sector &= ~(bio_sectors - 1); | 195 | sector &= ~(bio_sectors - 1); |
| 196 | 196 | ||
| 197 | /* | ||
| 198 | * The SCSI specification allows for the value | ||
| 199 | * returned by READ CAPACITY to be up to 75 2K | ||
| 200 | * sectors past the last readable block. | ||
| 201 | * Therefore, if we hit a medium error within the | ||
| 202 | * last 75 2K sectors, we decrease the saved size | ||
| 203 | * value. | ||
| 204 | */ | ||
| 197 | if (sector < get_capacity(info->disk) && | 205 | if (sector < get_capacity(info->disk) && |
| 198 | drive->probed_capacity - sector < 4 * 75) | 206 | drive->probed_capacity - sector < 4 * 75) |
| 199 | set_capacity(info->disk, sector); | 207 | set_capacity(info->disk, sector); |
| @@ -1790,15 +1798,17 @@ static void ide_cd_remove(ide_drive_t *drive) | |||
| 1790 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | 1798 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); |
| 1791 | 1799 | ||
| 1792 | ide_proc_unregister_driver(drive, info->driver); | 1800 | ide_proc_unregister_driver(drive, info->driver); |
| 1793 | 1801 | device_del(&info->dev); | |
| 1794 | del_gendisk(info->disk); | 1802 | del_gendisk(info->disk); |
| 1795 | 1803 | ||
| 1796 | ide_cd_put(info); | 1804 | mutex_lock(&idecd_ref_mutex); |
| 1805 | put_device(&info->dev); | ||
| 1806 | mutex_unlock(&idecd_ref_mutex); | ||
| 1797 | } | 1807 | } |
| 1798 | 1808 | ||
| 1799 | static void ide_cd_release(struct kref *kref) | 1809 | static void ide_cd_release(struct device *dev) |
| 1800 | { | 1810 | { |
| 1801 | struct cdrom_info *info = to_ide_drv(kref, cdrom_info); | 1811 | struct cdrom_info *info = to_ide_drv(dev, cdrom_info); |
| 1802 | struct cdrom_device_info *devinfo = &info->devinfo; | 1812 | struct cdrom_device_info *devinfo = &info->devinfo; |
| 1803 | ide_drive_t *drive = info->drive; | 1813 | ide_drive_t *drive = info->drive; |
| 1804 | struct gendisk *g = info->disk; | 1814 | struct gendisk *g = info->disk; |
| @@ -1997,7 +2007,12 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
| 1997 | 2007 | ||
| 1998 | ide_init_disk(g, drive); | 2008 | ide_init_disk(g, drive); |
| 1999 | 2009 | ||
| 2000 | kref_init(&info->kref); | 2010 | info->dev.parent = &drive->gendev; |
| 2011 | info->dev.release = ide_cd_release; | ||
| 2012 | dev_set_name(&info->dev, dev_name(&drive->gendev)); | ||
| 2013 | |||
| 2014 | if (device_register(&info->dev)) | ||
| 2015 | goto out_free_disk; | ||
| 2001 | 2016 | ||
| 2002 | info->drive = drive; | 2017 | info->drive = drive; |
| 2003 | info->driver = &ide_cdrom_driver; | 2018 | info->driver = &ide_cdrom_driver; |
| @@ -2011,7 +2026,7 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
| 2011 | g->driverfs_dev = &drive->gendev; | 2026 | g->driverfs_dev = &drive->gendev; |
| 2012 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; | 2027 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; |
| 2013 | if (ide_cdrom_setup(drive)) { | 2028 | if (ide_cdrom_setup(drive)) { |
| 2014 | ide_cd_release(&info->kref); | 2029 | put_device(&info->dev); |
| 2015 | goto failed; | 2030 | goto failed; |
| 2016 | } | 2031 | } |
| 2017 | 2032 | ||
| @@ -2021,6 +2036,8 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
| 2021 | add_disk(g); | 2036 | add_disk(g); |
| 2022 | return 0; | 2037 | return 0; |
| 2023 | 2038 | ||
| 2039 | out_free_disk: | ||
| 2040 | put_disk(g); | ||
| 2024 | out_free_cd: | 2041 | out_free_cd: |
| 2025 | kfree(info); | 2042 | kfree(info); |
| 2026 | failed: | 2043 | failed: |
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index ac40d6cb90a..c878bfcf111 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h | |||
| @@ -80,7 +80,7 @@ struct cdrom_info { | |||
| 80 | ide_drive_t *drive; | 80 | ide_drive_t *drive; |
| 81 | struct ide_driver *driver; | 81 | struct ide_driver *driver; |
| 82 | struct gendisk *disk; | 82 | struct gendisk *disk; |
| 83 | struct kref kref; | 83 | struct device dev; |
| 84 | 84 | ||
| 85 | /* Buffer for table of contents. NULL if we haven't allocated | 85 | /* Buffer for table of contents. NULL if we haven't allocated |
| 86 | a TOC buffer for this device yet. */ | 86 | a TOC buffer for this device yet. */ |
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c index 1146f4204c6..1f86dcbd2b1 100644 --- a/drivers/ide/ide-disk_proc.c +++ b/drivers/ide/ide-disk_proc.c | |||
| @@ -125,5 +125,5 @@ const struct ide_proc_devset ide_disk_settings[] = { | |||
| 125 | IDE_PROC_DEVSET(multcount, 0, 16), | 125 | IDE_PROC_DEVSET(multcount, 0, 16), |
| 126 | IDE_PROC_DEVSET(nowerr, 0, 1), | 126 | IDE_PROC_DEVSET(nowerr, 0, 1), |
| 127 | IDE_PROC_DEVSET(wcache, 0, 1), | 127 | IDE_PROC_DEVSET(wcache, 0, 1), |
| 128 | { 0 }, | 128 | { NULL }, |
| 129 | }; | 129 | }; |
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c index 3ec762cb60a..fcd4d8153df 100644 --- a/drivers/ide/ide-floppy_proc.c +++ b/drivers/ide/ide-floppy_proc.c | |||
| @@ -29,5 +29,5 @@ const struct ide_proc_devset ide_floppy_settings[] = { | |||
| 29 | IDE_PROC_DEVSET(bios_head, 0, 255), | 29 | IDE_PROC_DEVSET(bios_head, 0, 255), |
| 30 | IDE_PROC_DEVSET(bios_sect, 0, 63), | 30 | IDE_PROC_DEVSET(bios_sect, 0, 63), |
| 31 | IDE_PROC_DEVSET(ticks, 0, 255), | 31 | IDE_PROC_DEVSET(ticks, 0, 255), |
| 32 | { 0 }, | 32 | { NULL }, |
| 33 | }; | 33 | }; |
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 7857b209c6d..04710941990 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c | |||
| @@ -25,7 +25,7 @@ module_param(debug_mask, ulong, 0644); | |||
| 25 | 25 | ||
| 26 | static DEFINE_MUTEX(ide_disk_ref_mutex); | 26 | static DEFINE_MUTEX(ide_disk_ref_mutex); |
| 27 | 27 | ||
| 28 | static void ide_disk_release(struct kref *); | 28 | static void ide_disk_release(struct device *); |
| 29 | 29 | ||
| 30 | static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) | 30 | static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) |
| 31 | { | 31 | { |
| @@ -37,7 +37,7 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) | |||
| 37 | if (ide_device_get(idkp->drive)) | 37 | if (ide_device_get(idkp->drive)) |
| 38 | idkp = NULL; | 38 | idkp = NULL; |
| 39 | else | 39 | else |
| 40 | kref_get(&idkp->kref); | 40 | get_device(&idkp->dev); |
| 41 | } | 41 | } |
| 42 | mutex_unlock(&ide_disk_ref_mutex); | 42 | mutex_unlock(&ide_disk_ref_mutex); |
| 43 | return idkp; | 43 | return idkp; |
| @@ -48,7 +48,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp) | |||
| 48 | ide_drive_t *drive = idkp->drive; | 48 | ide_drive_t *drive = idkp->drive; |
| 49 | 49 | ||
| 50 | mutex_lock(&ide_disk_ref_mutex); | 50 | mutex_lock(&ide_disk_ref_mutex); |
| 51 | kref_put(&idkp->kref, ide_disk_release); | 51 | put_device(&idkp->dev); |
| 52 | ide_device_put(drive); | 52 | ide_device_put(drive); |
| 53 | mutex_unlock(&ide_disk_ref_mutex); | 53 | mutex_unlock(&ide_disk_ref_mutex); |
| 54 | } | 54 | } |
| @@ -66,17 +66,18 @@ static void ide_gd_remove(ide_drive_t *drive) | |||
| 66 | struct gendisk *g = idkp->disk; | 66 | struct gendisk *g = idkp->disk; |
| 67 | 67 | ||
| 68 | ide_proc_unregister_driver(drive, idkp->driver); | 68 | ide_proc_unregister_driver(drive, idkp->driver); |
| 69 | 69 | device_del(&idkp->dev); | |
| 70 | del_gendisk(g); | 70 | del_gendisk(g); |
| 71 | |||
| 72 | drive->disk_ops->flush(drive); | 71 | drive->disk_ops->flush(drive); |
| 73 | 72 | ||
| 74 | ide_disk_put(idkp); | 73 | mutex_lock(&ide_disk_ref_mutex); |
| 74 | put_device(&idkp->dev); | ||
| 75 | mutex_unlock(&ide_disk_ref_mutex); | ||
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | static void ide_disk_release(struct kref *kref) | 78 | static void ide_disk_release(struct device *dev) |
| 78 | { | 79 | { |
| 79 | struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj); | 80 | struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj); |
| 80 | ide_drive_t *drive = idkp->drive; | 81 | ide_drive_t *drive = idkp->drive; |
| 81 | struct gendisk *g = idkp->disk; | 82 | struct gendisk *g = idkp->disk; |
| 82 | 83 | ||
| @@ -348,7 +349,12 @@ static int ide_gd_probe(ide_drive_t *drive) | |||
| 348 | 349 | ||
| 349 | ide_init_disk(g, drive); | 350 | ide_init_disk(g, drive); |
| 350 | 351 | ||
| 351 | kref_init(&idkp->kref); | 352 | idkp->dev.parent = &drive->gendev; |
| 353 | idkp->dev.release = ide_disk_release; | ||
| 354 | dev_set_name(&idkp->dev, dev_name(&drive->gendev)); | ||
| 355 | |||
| 356 | if (device_register(&idkp->dev)) | ||
| 357 | goto out_free_disk; | ||
| 352 | 358 | ||
| 353 | idkp->drive = drive; | 359 | idkp->drive = drive; |
| 354 | idkp->driver = &ide_gd_driver; | 360 | idkp->driver = &ide_gd_driver; |
| @@ -373,6 +379,8 @@ static int ide_gd_probe(ide_drive_t *drive) | |||
| 373 | add_disk(g); | 379 | add_disk(g); |
| 374 | return 0; | 380 | return 0; |
| 375 | 381 | ||
| 382 | out_free_disk: | ||
| 383 | put_disk(g); | ||
| 376 | out_free_idkp: | 384 | out_free_idkp: |
| 377 | kfree(idkp); | 385 | kfree(idkp); |
| 378 | failed: | 386 | failed: |
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h index a86779f0756..b604bdd318a 100644 --- a/drivers/ide/ide-gd.h +++ b/drivers/ide/ide-gd.h | |||
| @@ -17,7 +17,7 @@ struct ide_disk_obj { | |||
| 17 | ide_drive_t *drive; | 17 | ide_drive_t *drive; |
| 18 | struct ide_driver *driver; | 18 | struct ide_driver *driver; |
| 19 | struct gendisk *disk; | 19 | struct gendisk *disk; |
| 20 | struct kref kref; | 20 | struct device dev; |
| 21 | unsigned int openers; /* protected by BKL for now */ | 21 | unsigned int openers; /* protected by BKL for now */ |
| 22 | 22 | ||
| 23 | /* Last failed packet command */ | 23 | /* Last failed packet command */ |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9ee51adf567..a9a6c208288 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -908,7 +908,7 @@ void ide_timer_expiry (unsigned long data) | |||
| 908 | ide_drive_t *uninitialized_var(drive); | 908 | ide_drive_t *uninitialized_var(drive); |
| 909 | ide_handler_t *handler; | 909 | ide_handler_t *handler; |
| 910 | unsigned long flags; | 910 | unsigned long flags; |
| 911 | unsigned long wait = -1; | 911 | int wait = -1; |
| 912 | int plug_device = 0; | 912 | int plug_device = 0; |
| 913 | 913 | ||
| 914 | spin_lock_irqsave(&hwif->lock, flags); | 914 | spin_lock_irqsave(&hwif->lock, flags); |
| @@ -1162,6 +1162,7 @@ out_early: | |||
| 1162 | 1162 | ||
| 1163 | return irq_ret; | 1163 | return irq_ret; |
| 1164 | } | 1164 | } |
| 1165 | EXPORT_SYMBOL_GPL(ide_intr); | ||
| 1165 | 1166 | ||
| 1166 | /** | 1167 | /** |
| 1167 | * ide_do_drive_cmd - issue IDE special command | 1168 | * ide_do_drive_cmd - issue IDE special command |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 753b92ebe0a..b1892bd95c6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
| @@ -315,6 +315,8 @@ void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, | |||
| 315 | u8 io_32bit = drive->io_32bit; | 315 | u8 io_32bit = drive->io_32bit; |
| 316 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 316 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
| 317 | 317 | ||
| 318 | len++; | ||
| 319 | |||
| 318 | if (io_32bit) { | 320 | if (io_32bit) { |
| 319 | unsigned long uninitialized_var(flags); | 321 | unsigned long uninitialized_var(flags); |
| 320 | 322 | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ce0818a993f..ee8e3e7cad5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -950,6 +950,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
| 950 | static int init_irq (ide_hwif_t *hwif) | 950 | static int init_irq (ide_hwif_t *hwif) |
| 951 | { | 951 | { |
| 952 | struct ide_io_ports *io_ports = &hwif->io_ports; | 952 | struct ide_io_ports *io_ports = &hwif->io_ports; |
| 953 | irq_handler_t irq_handler; | ||
| 953 | int sa = 0; | 954 | int sa = 0; |
| 954 | 955 | ||
| 955 | mutex_lock(&ide_cfg_mtx); | 956 | mutex_lock(&ide_cfg_mtx); |
| @@ -959,6 +960,10 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 959 | hwif->timer.function = &ide_timer_expiry; | 960 | hwif->timer.function = &ide_timer_expiry; |
| 960 | hwif->timer.data = (unsigned long)hwif; | 961 | hwif->timer.data = (unsigned long)hwif; |
| 961 | 962 | ||
| 963 | irq_handler = hwif->host->irq_handler; | ||
| 964 | if (irq_handler == NULL) | ||
| 965 | irq_handler = ide_intr; | ||
| 966 | |||
| 962 | #if defined(__mc68000__) | 967 | #if defined(__mc68000__) |
| 963 | sa = IRQF_SHARED; | 968 | sa = IRQF_SHARED; |
| 964 | #endif /* __mc68000__ */ | 969 | #endif /* __mc68000__ */ |
| @@ -969,7 +974,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 969 | if (io_ports->ctl_addr) | 974 | if (io_ports->ctl_addr) |
| 970 | hwif->tp_ops->set_irq(hwif, 1); | 975 | hwif->tp_ops->set_irq(hwif, 1); |
| 971 | 976 | ||
| 972 | if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) | 977 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) |
| 973 | goto out_up; | 978 | goto out_up; |
| 974 | 979 | ||
| 975 | if (!hwif->rqsize) { | 980 | if (!hwif->rqsize) { |
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 1d8978b3314..a7b9287ee0d 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
| @@ -231,7 +231,7 @@ static const struct ide_proc_devset ide_generic_settings[] = { | |||
| 231 | IDE_PROC_DEVSET(pio_mode, 0, 255), | 231 | IDE_PROC_DEVSET(pio_mode, 0, 255), |
| 232 | IDE_PROC_DEVSET(unmaskirq, 0, 1), | 232 | IDE_PROC_DEVSET(unmaskirq, 0, 1), |
| 233 | IDE_PROC_DEVSET(using_dma, 0, 1), | 233 | IDE_PROC_DEVSET(using_dma, 0, 1), |
| 234 | { 0 }, | 234 | { NULL }, |
| 235 | }; | 235 | }; |
| 236 | 236 | ||
| 237 | static void proc_ide_settings_warn(void) | 237 | static void proc_ide_settings_warn(void) |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d7ecd3c7975..4e6181c7bbd 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -169,7 +169,7 @@ typedef struct ide_tape_obj { | |||
| 169 | ide_drive_t *drive; | 169 | ide_drive_t *drive; |
| 170 | struct ide_driver *driver; | 170 | struct ide_driver *driver; |
| 171 | struct gendisk *disk; | 171 | struct gendisk *disk; |
| 172 | struct kref kref; | 172 | struct device dev; |
| 173 | 173 | ||
| 174 | /* | 174 | /* |
| 175 | * failed_pc points to the last failed packet command, or contains | 175 | * failed_pc points to the last failed packet command, or contains |
| @@ -267,7 +267,7 @@ static DEFINE_MUTEX(idetape_ref_mutex); | |||
| 267 | 267 | ||
| 268 | static struct class *idetape_sysfs_class; | 268 | static struct class *idetape_sysfs_class; |
| 269 | 269 | ||
| 270 | static void ide_tape_release(struct kref *); | 270 | static void ide_tape_release(struct device *); |
| 271 | 271 | ||
| 272 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) | 272 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) |
| 273 | { | 273 | { |
| @@ -279,7 +279,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) | |||
| 279 | if (ide_device_get(tape->drive)) | 279 | if (ide_device_get(tape->drive)) |
| 280 | tape = NULL; | 280 | tape = NULL; |
| 281 | else | 281 | else |
| 282 | kref_get(&tape->kref); | 282 | get_device(&tape->dev); |
| 283 | } | 283 | } |
| 284 | mutex_unlock(&idetape_ref_mutex); | 284 | mutex_unlock(&idetape_ref_mutex); |
| 285 | return tape; | 285 | return tape; |
| @@ -290,7 +290,7 @@ static void ide_tape_put(struct ide_tape_obj *tape) | |||
| 290 | ide_drive_t *drive = tape->drive; | 290 | ide_drive_t *drive = tape->drive; |
| 291 | 291 | ||
| 292 | mutex_lock(&idetape_ref_mutex); | 292 | mutex_lock(&idetape_ref_mutex); |
| 293 | kref_put(&tape->kref, ide_tape_release); | 293 | put_device(&tape->dev); |
| 294 | ide_device_put(drive); | 294 | ide_device_put(drive); |
| 295 | mutex_unlock(&idetape_ref_mutex); | 295 | mutex_unlock(&idetape_ref_mutex); |
| 296 | } | 296 | } |
| @@ -308,7 +308,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) | |||
| 308 | mutex_lock(&idetape_ref_mutex); | 308 | mutex_lock(&idetape_ref_mutex); |
| 309 | tape = idetape_devs[i]; | 309 | tape = idetape_devs[i]; |
| 310 | if (tape) | 310 | if (tape) |
| 311 | kref_get(&tape->kref); | 311 | get_device(&tape->dev); |
| 312 | mutex_unlock(&idetape_ref_mutex); | 312 | mutex_unlock(&idetape_ref_mutex); |
| 313 | return tape; | 313 | return tape; |
| 314 | } | 314 | } |
| @@ -2166,7 +2166,7 @@ static const struct ide_proc_devset idetape_settings[] = { | |||
| 2166 | __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), | 2166 | __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), |
| 2167 | __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, | 2167 | __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, |
| 2168 | mulf_tdsc, divf_tdsc), | 2168 | mulf_tdsc, divf_tdsc), |
| 2169 | { 0 }, | 2169 | { NULL }, |
| 2170 | }; | 2170 | }; |
| 2171 | #endif | 2171 | #endif |
| 2172 | 2172 | ||
| @@ -2256,15 +2256,17 @@ static void ide_tape_remove(ide_drive_t *drive) | |||
| 2256 | idetape_tape_t *tape = drive->driver_data; | 2256 | idetape_tape_t *tape = drive->driver_data; |
| 2257 | 2257 | ||
| 2258 | ide_proc_unregister_driver(drive, tape->driver); | 2258 | ide_proc_unregister_driver(drive, tape->driver); |
| 2259 | 2259 | device_del(&tape->dev); | |
| 2260 | ide_unregister_region(tape->disk); | 2260 | ide_unregister_region(tape->disk); |
| 2261 | 2261 | ||
| 2262 | ide_tape_put(tape); | 2262 | mutex_lock(&idetape_ref_mutex); |
| 2263 | put_device(&tape->dev); | ||
| 2264 | mutex_unlock(&idetape_ref_mutex); | ||
| 2263 | } | 2265 | } |
| 2264 | 2266 | ||
| 2265 | static void ide_tape_release(struct kref *kref) | 2267 | static void ide_tape_release(struct device *dev) |
| 2266 | { | 2268 | { |
| 2267 | struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj); | 2269 | struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj); |
| 2268 | ide_drive_t *drive = tape->drive; | 2270 | ide_drive_t *drive = tape->drive; |
| 2269 | struct gendisk *g = tape->disk; | 2271 | struct gendisk *g = tape->disk; |
| 2270 | 2272 | ||
| @@ -2407,7 +2409,12 @@ static int ide_tape_probe(ide_drive_t *drive) | |||
| 2407 | 2409 | ||
| 2408 | ide_init_disk(g, drive); | 2410 | ide_init_disk(g, drive); |
| 2409 | 2411 | ||
| 2410 | kref_init(&tape->kref); | 2412 | tape->dev.parent = &drive->gendev; |
| 2413 | tape->dev.release = ide_tape_release; | ||
| 2414 | dev_set_name(&tape->dev, dev_name(&drive->gendev)); | ||
| 2415 | |||
| 2416 | if (device_register(&tape->dev)) | ||
| 2417 | goto out_free_disk; | ||
| 2411 | 2418 | ||
| 2412 | tape->drive = drive; | 2419 | tape->drive = drive; |
| 2413 | tape->driver = &idetape_driver; | 2420 | tape->driver = &idetape_driver; |
| @@ -2436,6 +2443,8 @@ static int ide_tape_probe(ide_drive_t *drive) | |||
| 2436 | 2443 | ||
| 2437 | return 0; | 2444 | return 0; |
| 2438 | 2445 | ||
| 2446 | out_free_disk: | ||
| 2447 | put_disk(g); | ||
| 2439 | out_free_tape: | 2448 | out_free_tape: |
| 2440 | kfree(tape); | 2449 | kfree(tape); |
| 2441 | failed: | 2450 | failed: |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 258805da15c..0920e3b0c96 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
| @@ -337,6 +337,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | |||
| 337 | int a, b, i, j = 1; | 337 | int a, b, i, j = 1; |
| 338 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; | 338 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; |
| 339 | 339 | ||
| 340 | /* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */ | ||
| 340 | if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && | 341 | if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && |
| 341 | sscanf(s, "%d.%d", &a, &b) != 2) | 342 | sscanf(s, "%d.%d", &a, &b) != 2) |
| 342 | return -EINVAL; | 343 | return -EINVAL; |
| @@ -349,7 +350,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | |||
| 349 | if (j) | 350 | if (j) |
| 350 | *dev_param_mask |= (1 << i); | 351 | *dev_param_mask |= (1 << i); |
| 351 | else | 352 | else |
| 352 | *dev_param_mask &= (1 << i); | 353 | *dev_param_mask &= ~(1 << i); |
| 353 | 354 | ||
| 354 | return 0; | 355 | return 0; |
| 355 | } | 356 | } |
| @@ -392,6 +393,8 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp) | |||
| 392 | { | 393 | { |
| 393 | int a, b, c = 0, h = 0, s = 0, i, j = 1; | 394 | int a, b, c = 0, h = 0, s = 0, i, j = 1; |
| 394 | 395 | ||
| 396 | /* controller . device (0 or 1) : Cylinders , Heads , Sectors */ | ||
| 397 | /* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */ | ||
| 395 | if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && | 398 | if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && |
| 396 | sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) | 399 | sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) |
| 397 | return -EINVAL; | 400 | return -EINVAL; |
| @@ -407,7 +410,7 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp) | |||
| 407 | if (j) | 410 | if (j) |
| 408 | ide_disks |= (1 << i); | 411 | ide_disks |= (1 << i); |
| 409 | else | 412 | else |
| 410 | ide_disks &= (1 << i); | 413 | ide_disks &= ~(1 << i); |
| 411 | 414 | ||
| 412 | ide_disks_chs[i].cyl = c; | 415 | ide_disks_chs[i].cyl = c; |
| 413 | ide_disks_chs[i].head = h; | 416 | ide_disks_chs[i].head = h; |
| @@ -469,6 +472,8 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) | |||
| 469 | { | 472 | { |
| 470 | int i, j = 1; | 473 | int i, j = 1; |
| 471 | 474 | ||
| 475 | /* controller (ignore) */ | ||
| 476 | /* controller : 1 (ignore) | 0 (use) */ | ||
| 472 | if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) | 477 | if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) |
| 473 | return -EINVAL; | 478 | return -EINVAL; |
| 474 | 479 | ||
| @@ -478,7 +483,7 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) | |||
| 478 | if (j) | 483 | if (j) |
| 479 | ide_ignore_cable |= (1 << i); | 484 | ide_ignore_cable |= (1 << i); |
| 480 | else | 485 | else |
| 481 | ide_ignore_cable &= (1 << i); | 486 | ide_ignore_cable &= ~(1 << i); |
| 482 | 487 | ||
| 483 | return 0; | 488 | return 0; |
| 484 | } | 489 | } |
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index e1c4f543739..13b8153112e 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c | |||
| @@ -5,9 +5,8 @@ | |||
| 5 | * May be copied or modified under the terms of the GNU General Public License | 5 | * May be copied or modified under the terms of the GNU General Public License |
| 6 | * Based in part on the ITE vendor provided SCSI driver. | 6 | * Based in part on the ITE vendor provided SCSI driver. |
| 7 | * | 7 | * |
| 8 | * Documentation available from | 8 | * Documentation: |
| 9 | * http://www.ite.com.tw/pc/IT8212F_V04.pdf | 9 | * Datasheet is freely available, some other documents under NDA. |
| 10 | * Some other documents are NDA. | ||
| 11 | * | 10 | * |
| 12 | * The ITE8212 isn't exactly a standard IDE controller. It has two | 11 | * The ITE8212 isn't exactly a standard IDE controller. It has two |
| 13 | * modes. In pass through mode then it is an IDE controller. In its smart | 12 | * modes. In pass through mode then it is an IDE controller. In its smart |
diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h index 2727bcd2419..467373cab8e 100644 --- a/drivers/ieee1394/dma.h +++ b/drivers/ieee1394/dma.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <asm/types.h> | 13 | #include <asm/types.h> |
| 14 | 14 | ||
| 15 | struct file; | ||
| 15 | struct pci_dev; | 16 | struct pci_dev; |
| 16 | struct scatterlist; | 17 | struct scatterlist; |
| 17 | struct vm_area_struct; | 18 | struct vm_area_struct; |
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 2beb8d94f7b..87233800372 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c | |||
| @@ -1275,7 +1275,7 @@ static void __exit ieee1394_cleanup(void) | |||
| 1275 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); | 1275 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); |
| 1276 | } | 1276 | } |
| 1277 | 1277 | ||
| 1278 | module_init(ieee1394_init); | 1278 | fs_initcall(ieee1394_init); |
| 1279 | module_exit(ieee1394_cleanup); | 1279 | module_exit(ieee1394_cleanup); |
| 1280 | 1280 | ||
| 1281 | /* Exported symbols */ | 1281 | /* Exported symbols */ |
| @@ -1314,6 +1314,7 @@ EXPORT_SYMBOL(hpsb_make_lock64packet); | |||
| 1314 | EXPORT_SYMBOL(hpsb_make_phypacket); | 1314 | EXPORT_SYMBOL(hpsb_make_phypacket); |
| 1315 | EXPORT_SYMBOL(hpsb_read); | 1315 | EXPORT_SYMBOL(hpsb_read); |
| 1316 | EXPORT_SYMBOL(hpsb_write); | 1316 | EXPORT_SYMBOL(hpsb_write); |
| 1317 | EXPORT_SYMBOL(hpsb_lock); | ||
| 1317 | EXPORT_SYMBOL(hpsb_packet_success); | 1318 | EXPORT_SYMBOL(hpsb_packet_success); |
| 1318 | 1319 | ||
| 1319 | /** highlevel.c **/ | 1320 | /** highlevel.c **/ |
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 10c3d9f8c03..675b3135d5f 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c | |||
| @@ -501,8 +501,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, | |||
| 501 | if (length == 0) | 501 | if (length == 0) |
| 502 | return -EINVAL; | 502 | return -EINVAL; |
| 503 | 503 | ||
| 504 | BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet | ||
| 505 | |||
| 506 | packet = hpsb_make_readpacket(host, node, addr, length); | 504 | packet = hpsb_make_readpacket(host, node, addr, length); |
| 507 | 505 | ||
| 508 | if (!packet) { | 506 | if (!packet) { |
| @@ -550,8 +548,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, | |||
| 550 | if (length == 0) | 548 | if (length == 0) |
| 551 | return -EINVAL; | 549 | return -EINVAL; |
| 552 | 550 | ||
| 553 | BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet | ||
| 554 | |||
| 555 | packet = hpsb_make_writepacket(host, node, addr, buffer, length); | 551 | packet = hpsb_make_writepacket(host, node, addr, buffer, length); |
| 556 | 552 | ||
| 557 | if (!packet) | 553 | if (!packet) |
| @@ -570,3 +566,30 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, | |||
| 570 | 566 | ||
| 571 | return retval; | 567 | return retval; |
| 572 | } | 568 | } |
| 569 | |||
| 570 | int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, | ||
| 571 | u64 addr, int extcode, quadlet_t *data, quadlet_t arg) | ||
| 572 | { | ||
| 573 | struct hpsb_packet *packet; | ||
| 574 | int retval = 0; | ||
| 575 | |||
| 576 | packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg); | ||
| 577 | if (!packet) | ||
| 578 | return -ENOMEM; | ||
| 579 | |||
| 580 | packet->generation = generation; | ||
| 581 | retval = hpsb_send_packet_and_wait(packet); | ||
| 582 | if (retval < 0) | ||
| 583 | goto hpsb_lock_fail; | ||
| 584 | |||
| 585 | retval = hpsb_packet_success(packet); | ||
| 586 | |||
| 587 | if (retval == 0) | ||
| 588 | *data = packet->data[0]; | ||
| 589 | |||
| 590 | hpsb_lock_fail: | ||
| 591 | hpsb_free_tlabel(packet); | ||
| 592 | hpsb_free_packet(packet); | ||
| 593 | |||
| 594 | return retval; | ||
| 595 | } | ||
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h index d2d5bc3546d..20b693be14b 100644 --- a/drivers/ieee1394/ieee1394_transactions.h +++ b/drivers/ieee1394/ieee1394_transactions.h | |||
| @@ -30,6 +30,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, | |||
| 30 | u64 addr, quadlet_t *buffer, size_t length); | 30 | u64 addr, quadlet_t *buffer, size_t length); |
| 31 | int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, | 31 | int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, |
| 32 | u64 addr, quadlet_t *buffer, size_t length); | 32 | u64 addr, quadlet_t *buffer, size_t length); |
| 33 | int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, | ||
| 34 | u64 addr, int extcode, quadlet_t *data, quadlet_t arg); | ||
| 33 | 35 | ||
| 34 | #ifdef HPSB_DEBUG_TLABELS | 36 | #ifdef HPSB_DEBUG_TLABELS |
| 35 | extern spinlock_t hpsb_tlabel_lock; | 37 | extern spinlock_t hpsb_tlabel_lock; |
diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h index b5de5f21ef7..c2089c093aa 100644 --- a/drivers/ieee1394/iso.h +++ b/drivers/ieee1394/iso.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #define IEEE1394_ISO_H | 13 | #define IEEE1394_ISO_H |
| 14 | 14 | ||
| 15 | #include <linux/spinlock_types.h> | 15 | #include <linux/spinlock_types.h> |
| 16 | #include <linux/wait.h> | ||
| 16 | #include <asm/atomic.h> | 17 | #include <asm/atomic.h> |
| 17 | #include <asm/types.h> | 18 | #include <asm/types.h> |
| 18 | 19 | ||
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 906c5a98d81..53aada5bbe1 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
| @@ -971,6 +971,9 @@ static struct unit_directory *nodemgr_process_unit_directory | |||
| 971 | ud->ud_kv = ud_kv; | 971 | ud->ud_kv = ud_kv; |
| 972 | ud->id = (*id)++; | 972 | ud->id = (*id)++; |
| 973 | 973 | ||
| 974 | /* inherit vendor_id from root directory if none exists in unit dir */ | ||
| 975 | ud->vendor_id = ne->vendor_id; | ||
| 976 | |||
| 974 | csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) { | 977 | csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) { |
| 975 | switch (kv->key.id) { | 978 | switch (kv->key.id) { |
| 976 | case CSR1212_KV_ID_VENDOR: | 979 | case CSR1212_KV_ID_VENDOR: |
| @@ -1265,7 +1268,8 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, | |||
| 1265 | csr1212_destroy_csr(csr); | 1268 | csr1212_destroy_csr(csr); |
| 1266 | } | 1269 | } |
| 1267 | 1270 | ||
| 1268 | /* Mark the node current */ | 1271 | /* Finally, mark the node current */ |
| 1272 | smp_wmb(); | ||
| 1269 | ne->generation = generation; | 1273 | ne->generation = generation; |
| 1270 | 1274 | ||
| 1271 | if (ne->in_limbo) { | 1275 | if (ne->in_limbo) { |
| @@ -1798,7 +1802,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet) | |||
| 1798 | { | 1802 | { |
| 1799 | packet->host = ne->host; | 1803 | packet->host = ne->host; |
| 1800 | packet->generation = ne->generation; | 1804 | packet->generation = ne->generation; |
| 1801 | barrier(); | 1805 | smp_rmb(); |
| 1802 | packet->node_id = ne->nodeid; | 1806 | packet->node_id = ne->nodeid; |
| 1803 | } | 1807 | } |
| 1804 | 1808 | ||
| @@ -1807,7 +1811,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr, | |||
| 1807 | { | 1811 | { |
| 1808 | unsigned int generation = ne->generation; | 1812 | unsigned int generation = ne->generation; |
| 1809 | 1813 | ||
| 1810 | barrier(); | 1814 | smp_rmb(); |
| 1811 | return hpsb_write(ne->host, ne->nodeid, generation, | 1815 | return hpsb_write(ne->host, ne->nodeid, generation, |
| 1812 | addr, buffer, length); | 1816 | addr, buffer, length); |
| 1813 | } | 1817 | } |
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 15ea09733e8..ee5acdbd114 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h | |||
| @@ -21,9 +21,11 @@ | |||
| 21 | #define _IEEE1394_NODEMGR_H | 21 | #define _IEEE1394_NODEMGR_H |
| 22 | 22 | ||
| 23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 24 | #include <asm/system.h> | ||
| 24 | #include <asm/types.h> | 25 | #include <asm/types.h> |
| 25 | 26 | ||
| 26 | #include "ieee1394_core.h" | 27 | #include "ieee1394_core.h" |
| 28 | #include "ieee1394_transactions.h" | ||
| 27 | #include "ieee1394_types.h" | 29 | #include "ieee1394_types.h" |
| 28 | 30 | ||
| 29 | struct csr1212_csr; | 31 | struct csr1212_csr; |
| @@ -154,6 +156,22 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne) | |||
| 154 | void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet); | 156 | void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet); |
| 155 | int hpsb_node_write(struct node_entry *ne, u64 addr, | 157 | int hpsb_node_write(struct node_entry *ne, u64 addr, |
| 156 | quadlet_t *buffer, size_t length); | 158 | quadlet_t *buffer, size_t length); |
| 159 | static inline int hpsb_node_read(struct node_entry *ne, u64 addr, | ||
| 160 | quadlet_t *buffer, size_t length) | ||
| 161 | { | ||
| 162 | unsigned int g = ne->generation; | ||
| 163 | |||
| 164 | smp_rmb(); | ||
| 165 | return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length); | ||
| 166 | } | ||
| 167 | static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode, | ||
| 168 | quadlet_t *buffer, quadlet_t arg) | ||
| 169 | { | ||
| 170 | unsigned int g = ne->generation; | ||
| 171 | |||
| 172 | smp_rmb(); | ||
| 173 | return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg); | ||
| 174 | } | ||
| 157 | int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)); | 175 | int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)); |
| 158 | 176 | ||
| 159 | int init_ieee1394_nodemgr(void); | 177 | int init_ieee1394_nodemgr(void); |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index c3c8b9bc40a..45470f18d7e 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -839,7 +839,7 @@ static void atkbd_disconnect(struct serio *serio) | |||
| 839 | */ | 839 | */ |
| 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) |
| 841 | { | 841 | { |
| 842 | const unsigned int forced_release_keys[] = { | 842 | static const unsigned int forced_release_keys[] = { |
| 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, |
| 844 | }; | 844 | }; |
| 845 | int i; | 845 | int i; |
| @@ -856,7 +856,7 @@ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | |||
| 856 | */ | 856 | */ |
| 857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) | 857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) |
| 858 | { | 858 | { |
| 859 | const unsigned int forced_release_keys[] = { | 859 | static const unsigned int forced_release_keys[] = { |
| 860 | 0x94, | 860 | 0x94, |
| 861 | }; | 861 | }; |
| 862 | int i; | 862 | int i; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 19284016e0f..ee855c5202e 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
| @@ -209,8 +209,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 209 | goto out; | 209 | goto out; |
| 210 | } | 210 | } |
| 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_ERR DRV_NAME |
| 215 | ": Invalid Debounce/Columdrive Time from pdata\n"); | 215 | ": Invalid Debounce/Columdrive Time from pdata\n"); |
| 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index c8ed065ea0c..abb04c82c62 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
| @@ -288,7 +288,7 @@ static int corgikbd_resume(struct platform_device *dev) | |||
| 288 | #define corgikbd_resume NULL | 288 | #define corgikbd_resume NULL |
| 289 | #endif | 289 | #endif |
| 290 | 290 | ||
| 291 | static int __init corgikbd_probe(struct platform_device *pdev) | 291 | static int __devinit corgikbd_probe(struct platform_device *pdev) |
| 292 | { | 292 | { |
| 293 | struct corgikbd *corgikbd; | 293 | struct corgikbd *corgikbd; |
| 294 | struct input_dev *input_dev; | 294 | struct input_dev *input_dev; |
| @@ -368,7 +368,7 @@ static int __init corgikbd_probe(struct platform_device *pdev) | |||
| 368 | return err; | 368 | return err; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static int corgikbd_remove(struct platform_device *pdev) | 371 | static int __devexit corgikbd_remove(struct platform_device *pdev) |
| 372 | { | 372 | { |
| 373 | int i; | 373 | int i; |
| 374 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); | 374 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); |
| @@ -388,7 +388,7 @@ static int corgikbd_remove(struct platform_device *pdev) | |||
| 388 | 388 | ||
| 389 | static struct platform_driver corgikbd_driver = { | 389 | static struct platform_driver corgikbd_driver = { |
| 390 | .probe = corgikbd_probe, | 390 | .probe = corgikbd_probe, |
| 391 | .remove = corgikbd_remove, | 391 | .remove = __devexit_p(corgikbd_remove), |
| 392 | .suspend = corgikbd_suspend, | 392 | .suspend = corgikbd_suspend, |
| 393 | .resume = corgikbd_resume, | 393 | .resume = corgikbd_resume, |
| 394 | .driver = { | 394 | .driver = { |
| @@ -397,7 +397,7 @@ static struct platform_driver corgikbd_driver = { | |||
| 397 | }, | 397 | }, |
| 398 | }; | 398 | }; |
| 399 | 399 | ||
| 400 | static int __devinit corgikbd_init(void) | 400 | static int __init corgikbd_init(void) |
| 401 | { | 401 | { |
| 402 | return platform_driver_register(&corgikbd_driver); | 402 | return platform_driver_register(&corgikbd_driver); |
| 403 | } | 403 | } |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3f3d1198cdb..058fa8b02c2 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
| @@ -279,7 +279,7 @@ static int omap_kp_resume(struct platform_device *dev) | |||
| 279 | #define omap_kp_resume NULL | 279 | #define omap_kp_resume NULL |
| 280 | #endif | 280 | #endif |
| 281 | 281 | ||
| 282 | static int __init omap_kp_probe(struct platform_device *pdev) | 282 | static int __devinit omap_kp_probe(struct platform_device *pdev) |
| 283 | { | 283 | { |
| 284 | struct omap_kp *omap_kp; | 284 | struct omap_kp *omap_kp; |
| 285 | struct input_dev *input_dev; | 285 | struct input_dev *input_dev; |
| @@ -422,7 +422,7 @@ err1: | |||
| 422 | return -EINVAL; | 422 | return -EINVAL; |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | static int omap_kp_remove(struct platform_device *pdev) | 425 | static int __devexit omap_kp_remove(struct platform_device *pdev) |
| 426 | { | 426 | { |
| 427 | struct omap_kp *omap_kp = platform_get_drvdata(pdev); | 427 | struct omap_kp *omap_kp = platform_get_drvdata(pdev); |
| 428 | 428 | ||
| @@ -454,7 +454,7 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
| 454 | 454 | ||
| 455 | static struct platform_driver omap_kp_driver = { | 455 | static struct platform_driver omap_kp_driver = { |
| 456 | .probe = omap_kp_probe, | 456 | .probe = omap_kp_probe, |
| 457 | .remove = omap_kp_remove, | 457 | .remove = __devexit_p(omap_kp_remove), |
| 458 | .suspend = omap_kp_suspend, | 458 | .suspend = omap_kp_suspend, |
| 459 | .resume = omap_kp_resume, | 459 | .resume = omap_kp_resume, |
| 460 | .driver = { | 460 | .driver = { |
| @@ -463,7 +463,7 @@ static struct platform_driver omap_kp_driver = { | |||
| 463 | }, | 463 | }, |
| 464 | }; | 464 | }; |
| 465 | 465 | ||
| 466 | static int __devinit omap_kp_init(void) | 466 | static int __init omap_kp_init(void) |
| 467 | { | 467 | { |
| 468 | printk(KERN_INFO "OMAP Keypad Driver\n"); | 468 | printk(KERN_INFO "OMAP Keypad Driver\n"); |
| 469 | return platform_driver_register(&omap_kp_driver); | 469 | return platform_driver_register(&omap_kp_driver); |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index c48b76a46a5..9d1781a618e 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c | |||
| @@ -343,7 +343,7 @@ static int spitzkbd_resume(struct platform_device *dev) | |||
| 343 | #define spitzkbd_resume NULL | 343 | #define spitzkbd_resume NULL |
| 344 | #endif | 344 | #endif |
| 345 | 345 | ||
| 346 | static int __init spitzkbd_probe(struct platform_device *dev) | 346 | static int __devinit spitzkbd_probe(struct platform_device *dev) |
| 347 | { | 347 | { |
| 348 | struct spitzkbd *spitzkbd; | 348 | struct spitzkbd *spitzkbd; |
| 349 | struct input_dev *input_dev; | 349 | struct input_dev *input_dev; |
| @@ -444,7 +444,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) | |||
| 444 | return err; | 444 | return err; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static int spitzkbd_remove(struct platform_device *dev) | 447 | static int __devexit spitzkbd_remove(struct platform_device *dev) |
| 448 | { | 448 | { |
| 449 | int i; | 449 | int i; |
| 450 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | 450 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); |
| @@ -470,7 +470,7 @@ static int spitzkbd_remove(struct platform_device *dev) | |||
| 470 | 470 | ||
| 471 | static struct platform_driver spitzkbd_driver = { | 471 | static struct platform_driver spitzkbd_driver = { |
| 472 | .probe = spitzkbd_probe, | 472 | .probe = spitzkbd_probe, |
| 473 | .remove = spitzkbd_remove, | 473 | .remove = __devexit_p(spitzkbd_remove), |
| 474 | .suspend = spitzkbd_suspend, | 474 | .suspend = spitzkbd_suspend, |
| 475 | .resume = spitzkbd_resume, | 475 | .resume = spitzkbd_resume, |
| 476 | .driver = { | 476 | .driver = { |
| @@ -479,7 +479,7 @@ static struct platform_driver spitzkbd_driver = { | |||
| 479 | }, | 479 | }, |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | static int __devinit spitzkbd_init(void) | 482 | static int __init spitzkbd_init(void) |
| 483 | { | 483 | { |
| 484 | return platform_driver_register(&spitzkbd_driver); | 484 | return platform_driver_register(&spitzkbd_driver); |
| 485 | } | 485 | } |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 093c8c1bca7..9705f3a00a3 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS | |||
| 70 | config MOUSE_PS2_LIFEBOOK | 70 | config MOUSE_PS2_LIFEBOOK |
| 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED |
| 72 | default y | 72 | default y |
| 73 | depends on MOUSE_PS2 | 73 | depends on MOUSE_PS2 && X86 |
| 74 | help | 74 | help |
| 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 | 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 |
| 76 | TouchScreen connected to your system. | 76 | TouchScreen connected to your system. |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b9a25d57bc5..6ab0eb1ada1 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -542,7 +542,7 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) | |||
| 542 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 542 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
| 543 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 543 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
| 544 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 544 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
| 545 | pr_err("elantech.c: sending Elantech magic knock failed.\n"); | 545 | pr_debug("elantech.c: sending Elantech magic knock failed.\n"); |
| 546 | return -1; | 546 | return -1; |
| 547 | } | 547 | } |
| 548 | 548 | ||
| @@ -551,8 +551,27 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) | |||
| 551 | * set of magic numbers | 551 | * set of magic numbers |
| 552 | */ | 552 | */ |
| 553 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { | 553 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { |
| 554 | pr_info("elantech.c: unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | 554 | pr_debug("elantech.c: " |
| 555 | param[0], param[1], param[2]); | 555 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", |
| 556 | param[0], param[1], param[2]); | ||
| 557 | return -1; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* | ||
| 561 | * Query touchpad's firmware version and see if it reports known | ||
| 562 | * value to avoid mis-detection. Logitech mice are known to respond | ||
| 563 | * to Elantech magic knock and there might be more. | ||
| 564 | */ | ||
| 565 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | ||
| 566 | pr_debug("elantech.c: failed to query firmware version.\n"); | ||
| 567 | return -1; | ||
| 568 | } | ||
| 569 | |||
| 570 | pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | ||
| 571 | param[0], param[1], param[2]); | ||
| 572 | |||
| 573 | if (param[0] == 0 || param[1] != 0) { | ||
| 574 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | ||
| 556 | return -1; | 575 | return -1; |
| 557 | } | 576 | } |
| 558 | 577 | ||
| @@ -600,8 +619,7 @@ int elantech_init(struct psmouse *psmouse) | |||
| 600 | int i, error; | 619 | int i, error; |
| 601 | unsigned char param[3]; | 620 | unsigned char param[3]; |
| 602 | 621 | ||
| 603 | etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 622 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
| 604 | psmouse->private = etd; | ||
| 605 | if (!etd) | 623 | if (!etd) |
| 606 | return -1; | 624 | return -1; |
| 607 | 625 | ||
| @@ -610,14 +628,12 @@ int elantech_init(struct psmouse *psmouse) | |||
| 610 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; | 628 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; |
| 611 | 629 | ||
| 612 | /* | 630 | /* |
| 613 | * Find out what version hardware this is | 631 | * Do the version query again so we can store the result |
| 614 | */ | 632 | */ |
| 615 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 633 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
| 616 | pr_err("elantech.c: failed to query firmware version.\n"); | 634 | pr_err("elantech.c: failed to query firmware version.\n"); |
| 617 | goto init_fail; | 635 | goto init_fail; |
| 618 | } | 636 | } |
| 619 | pr_info("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | ||
| 620 | param[0], param[1], param[2]); | ||
| 621 | etd->fw_version_maj = param[0]; | 637 | etd->fw_version_maj = param[0]; |
| 622 | etd->fw_version_min = param[2]; | 638 | etd->fw_version_min = param[2]; |
| 623 | 639 | ||
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index d297accf9a7..1e827ad0afb 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c | |||
| @@ -83,7 +83,7 @@ static int write_tbcr(struct pxa930_trkball *trkball, int v) | |||
| 83 | 83 | ||
| 84 | __raw_writel(v, trkball->mmio_base + TBCR); | 84 | __raw_writel(v, trkball->mmio_base + TBCR); |
| 85 | 85 | ||
| 86 | while (i--) { | 86 | while (--i) { |
| 87 | if (__raw_readl(trkball->mmio_base + TBCR) == v) | 87 | if (__raw_readl(trkball->mmio_base + TBCR) == v) |
| 88 | break; | 88 | break; |
| 89 | msleep(1); | 89 | msleep(1); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 865fc69e9bc..f3e4f7b0240 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -182,11 +182,6 @@ static int synaptics_identify(struct psmouse *psmouse) | |||
| 182 | 182 | ||
| 183 | static int synaptics_query_hardware(struct psmouse *psmouse) | 183 | static int synaptics_query_hardware(struct psmouse *psmouse) |
| 184 | { | 184 | { |
| 185 | int retries = 0; | ||
| 186 | |||
| 187 | while ((retries++ < 3) && psmouse_reset(psmouse)) | ||
| 188 | /* empty */; | ||
| 189 | |||
| 190 | if (synaptics_identify(psmouse)) | 185 | if (synaptics_identify(psmouse)) |
| 191 | return -1; | 186 | return -1; |
| 192 | if (synaptics_model_id(psmouse)) | 187 | if (synaptics_model_id(psmouse)) |
| @@ -582,6 +577,8 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
| 582 | struct synaptics_data *priv = psmouse->private; | 577 | struct synaptics_data *priv = psmouse->private; |
| 583 | struct synaptics_data old_priv = *priv; | 578 | struct synaptics_data old_priv = *priv; |
| 584 | 579 | ||
| 580 | psmouse_reset(psmouse); | ||
| 581 | |||
| 585 | if (synaptics_detect(psmouse, 0)) | 582 | if (synaptics_detect(psmouse, 0)) |
| 586 | return -1; | 583 | return -1; |
| 587 | 584 | ||
| @@ -640,6 +637,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 640 | if (!priv) | 637 | if (!priv) |
| 641 | return -1; | 638 | return -1; |
| 642 | 639 | ||
| 640 | psmouse_reset(psmouse); | ||
| 641 | |||
| 643 | if (synaptics_query_hardware(psmouse)) { | 642 | if (synaptics_query_hardware(psmouse)) { |
| 644 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 643 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); |
| 645 | goto init_fail; | 644 | goto init_fail; |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index b10ffae7c39..e29cdc13a19 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
| @@ -57,7 +57,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val) | |||
| 57 | struct amba_kmi_port *kmi = io->port_data; | 57 | struct amba_kmi_port *kmi = io->port_data; |
| 58 | unsigned int timeleft = 10000; /* timeout in 100ms */ | 58 | unsigned int timeleft = 10000; /* timeout in 100ms */ |
| 59 | 59 | ||
| 60 | while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) | 60 | while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft) |
| 61 | udelay(10); | 61 | udelay(10); |
| 62 | 62 | ||
| 63 | if (timeleft) | 63 | if (timeleft) |
| @@ -129,8 +129,8 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) | |||
| 129 | io->write = amba_kmi_write; | 129 | io->write = amba_kmi_write; |
| 130 | io->open = amba_kmi_open; | 130 | io->open = amba_kmi_open; |
| 131 | io->close = amba_kmi_close; | 131 | io->close = amba_kmi_close; |
| 132 | strlcpy(io->name, dev->dev.bus_id, sizeof(io->name)); | 132 | strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name)); |
| 133 | strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys)); | 133 | strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys)); |
| 134 | io->port_data = kmi; | 134 | io->port_data = kmi; |
| 135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
| 136 | 136 | ||
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index adc3bd6e7f7..bd0f92d9f40 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
| @@ -359,7 +359,7 @@ static int __init gscps2_probe(struct parisc_device *dev) | |||
| 359 | 359 | ||
| 360 | snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", | 360 | snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", |
| 361 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); | 361 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); |
| 362 | strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); | 362 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); |
| 363 | serio->id.type = SERIO_8042; | 363 | serio->id.type = SERIO_8042; |
| 364 | serio->write = gscps2_write; | 364 | serio->write = gscps2_write; |
| 365 | serio->open = gscps2_open; | 365 | serio->open = gscps2_open; |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2ad88780a17..57953c0eb82 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
| @@ -246,8 +246,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) | |||
| 246 | serio->write = ps2_write; | 246 | serio->write = ps2_write; |
| 247 | serio->open = ps2_open; | 247 | serio->open = ps2_open; |
| 248 | serio->close = ps2_close; | 248 | serio->close = ps2_close; |
| 249 | strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name)); | 249 | strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name)); |
| 250 | strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); | 250 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); |
| 251 | serio->port_data = ps2if; | 251 | serio->port_data = ps2if; |
| 252 | serio->dev.parent = &dev->dev; | 252 | serio->dev.parent = &dev->dev; |
| 253 | ps2if->io = serio; | 253 | ps2if->io = serio; |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index a89a6a8f05e..055969e8be1 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -236,7 +236,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 236 | ts_dev->bufferedmeasure = 0; | 236 | ts_dev->bufferedmeasure = 0; |
| 237 | 237 | ||
| 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), | 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), |
| 239 | "%s/input0", pdev->dev.bus_id); | 239 | "%s/input0", dev_name(&pdev->dev)); |
| 240 | 240 | ||
| 241 | input_dev->name = "atmel touch screen controller"; | 241 | input_dev->name = "atmel touch screen controller"; |
| 242 | input_dev->phys = ts_dev->phys; | 242 | input_dev->phys = ts_dev->phys; |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 65202c9f63f..3fb51b54fe6 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c | |||
| @@ -268,7 +268,7 @@ static int corgits_resume(struct platform_device *dev) | |||
| 268 | #define corgits_resume NULL | 268 | #define corgits_resume NULL |
| 269 | #endif | 269 | #endif |
| 270 | 270 | ||
| 271 | static int __init corgits_probe(struct platform_device *pdev) | 271 | static int __devinit corgits_probe(struct platform_device *pdev) |
| 272 | { | 272 | { |
| 273 | struct corgi_ts *corgi_ts; | 273 | struct corgi_ts *corgi_ts; |
| 274 | struct input_dev *input_dev; | 274 | struct input_dev *input_dev; |
| @@ -343,7 +343,7 @@ static int __init corgits_probe(struct platform_device *pdev) | |||
| 343 | return err; | 343 | return err; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static int corgits_remove(struct platform_device *pdev) | 346 | static int __devexit corgits_remove(struct platform_device *pdev) |
| 347 | { | 347 | { |
| 348 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); | 348 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); |
| 349 | 349 | ||
| @@ -352,12 +352,13 @@ static int corgits_remove(struct platform_device *pdev) | |||
| 352 | corgi_ts->machinfo->put_hsync(); | 352 | corgi_ts->machinfo->put_hsync(); |
| 353 | input_unregister_device(corgi_ts->input); | 353 | input_unregister_device(corgi_ts->input); |
| 354 | kfree(corgi_ts); | 354 | kfree(corgi_ts); |
| 355 | |||
| 355 | return 0; | 356 | return 0; |
| 356 | } | 357 | } |
| 357 | 358 | ||
| 358 | static struct platform_driver corgits_driver = { | 359 | static struct platform_driver corgits_driver = { |
| 359 | .probe = corgits_probe, | 360 | .probe = corgits_probe, |
| 360 | .remove = corgits_remove, | 361 | .remove = __devexit_p(corgits_remove), |
| 361 | .suspend = corgits_suspend, | 362 | .suspend = corgits_suspend, |
| 362 | .resume = corgits_resume, | 363 | .resume = corgits_resume, |
| 363 | .driver = { | 364 | .driver = { |
| @@ -366,7 +367,7 @@ static struct platform_driver corgits_driver = { | |||
| 366 | }, | 367 | }, |
| 367 | }; | 368 | }; |
| 368 | 369 | ||
| 369 | static int __devinit corgits_init(void) | 370 | static int __init corgits_init(void) |
| 370 | { | 371 | { |
| 371 | return platform_driver_register(&corgits_driver); | 372 | return platform_driver_register(&corgits_driver); |
| 372 | } | 373 | } |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index b75dc299057..4ab07024689 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
| @@ -289,7 +289,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 289 | 289 | ||
| 290 | pdata->init_platform_hw(); | 290 | pdata->init_platform_hw(); |
| 291 | 291 | ||
| 292 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id); | 292 | snprintf(ts->phys, sizeof(ts->phys), |
| 293 | "%s/input0", dev_name(&client->dev)); | ||
| 293 | 294 | ||
| 294 | input_dev->name = "TSC2007 Touchscreen"; | 295 | input_dev->name = "TSC2007 Touchscreen"; |
| 295 | input_dev->phys = ts->phys; | 296 | input_dev->phys = ts->phys; |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 5080b26ba16..fb7cb9bdfbd 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -60,6 +60,10 @@ static int swap_xy; | |||
| 60 | module_param(swap_xy, bool, 0644); | 60 | module_param(swap_xy, bool, 0644); |
| 61 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 61 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); |
| 62 | 62 | ||
| 63 | static int hwcalib_xy; | ||
| 64 | module_param(hwcalib_xy, bool, 0644); | ||
| 65 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | ||
| 66 | |||
| 63 | /* device specifc data/functions */ | 67 | /* device specifc data/functions */ |
| 64 | struct usbtouch_usb; | 68 | struct usbtouch_usb; |
| 65 | struct usbtouch_device_info { | 69 | struct usbtouch_device_info { |
| @@ -118,6 +122,7 @@ enum { | |||
| 118 | 122 | ||
| 119 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| 120 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ | 124 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ |
| 125 | | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | ||
| 121 | | USB_DEVICE_ID_MATCH_DEVICE, \ | 126 | | USB_DEVICE_ID_MATCH_DEVICE, \ |
| 122 | .idVendor = (vend), \ | 127 | .idVendor = (vend), \ |
| 123 | .idProduct = (prod), \ | 128 | .idProduct = (prod), \ |
| @@ -260,8 +265,13 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 260 | 265 | ||
| 261 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 266 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
| 262 | { | 267 | { |
| 263 | dev->x = (pkt[8] << 8) | pkt[7]; | 268 | if (hwcalib_xy) { |
| 264 | dev->y = (pkt[10] << 8) | pkt[9]; | 269 | dev->x = (pkt[4] << 8) | pkt[3]; |
| 270 | dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); | ||
| 271 | } else { | ||
| 272 | dev->x = (pkt[8] << 8) | pkt[7]; | ||
| 273 | dev->y = (pkt[10] << 8) | pkt[9]; | ||
| 274 | } | ||
| 265 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; | 275 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; |
| 266 | 276 | ||
| 267 | return 1; | 277 | return 1; |
| @@ -294,6 +304,12 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
| 294 | return ret; | 304 | return ret; |
| 295 | } | 305 | } |
| 296 | 306 | ||
| 307 | /* Default min/max xy are the raw values, override if using hw-calib */ | ||
| 308 | if (hwcalib_xy) { | ||
| 309 | input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); | ||
| 310 | input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); | ||
| 311 | } | ||
| 312 | |||
| 297 | return 0; | 313 | return 0; |
| 298 | } | 314 | } |
| 299 | #endif | 315 | #endif |
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c index 712220cef13..7f16d75d2d8 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c | |||
| @@ -54,7 +54,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n) | |||
| 54 | spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); | 54 | spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); |
| 55 | pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, | 55 | pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, |
| 56 | ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); | 56 | ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); |
| 57 | pr_debug("%s: copying %d bytes from %#lx to %#lx\n", | 57 | pr_debug("%s: copying %zu bytes from %#lx to %#lx\n", |
| 58 | sc_adapter[card]->devicename, n, | 58 | sc_adapter[card]->devicename, n, |
| 59 | (unsigned long) src, | 59 | (unsigned long) src, |
| 60 | sc_adapter[card]->rambase + ((unsigned long) dest %0x4000)); | 60 | sc_adapter[card]->rambase + ((unsigned long) dest %0x4000)); |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 01e3cffd03b..e2466425d9c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -1237,8 +1237,9 @@ static void end_sync_write(struct bio *bio, int error) | |||
| 1237 | update_head_pos(mirror, r1_bio); | 1237 | update_head_pos(mirror, r1_bio); |
| 1238 | 1238 | ||
| 1239 | if (atomic_dec_and_test(&r1_bio->remaining)) { | 1239 | if (atomic_dec_and_test(&r1_bio->remaining)) { |
| 1240 | md_done_sync(mddev, r1_bio->sectors, uptodate); | 1240 | sector_t s = r1_bio->sectors; |
| 1241 | put_buf(r1_bio); | 1241 | put_buf(r1_bio); |
| 1242 | md_done_sync(mddev, s, uptodate); | ||
| 1242 | } | 1243 | } |
| 1243 | } | 1244 | } |
| 1244 | 1245 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 6736d6dff98..7301631abe0 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -1236,6 +1236,7 @@ static void end_sync_read(struct bio *bio, int error) | |||
| 1236 | /* for reconstruct, we always reschedule after a read. | 1236 | /* for reconstruct, we always reschedule after a read. |
| 1237 | * for resync, only after all reads | 1237 | * for resync, only after all reads |
| 1238 | */ | 1238 | */ |
| 1239 | rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev); | ||
| 1239 | if (test_bit(R10BIO_IsRecover, &r10_bio->state) || | 1240 | if (test_bit(R10BIO_IsRecover, &r10_bio->state) || |
| 1240 | atomic_dec_and_test(&r10_bio->remaining)) { | 1241 | atomic_dec_and_test(&r10_bio->remaining)) { |
| 1241 | /* we have read all the blocks, | 1242 | /* we have read all the blocks, |
| @@ -1243,7 +1244,6 @@ static void end_sync_read(struct bio *bio, int error) | |||
| 1243 | */ | 1244 | */ |
| 1244 | reschedule_retry(r10_bio); | 1245 | reschedule_retry(r10_bio); |
| 1245 | } | 1246 | } |
| 1246 | rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev); | ||
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| 1249 | static void end_sync_write(struct bio *bio, int error) | 1249 | static void end_sync_write(struct bio *bio, int error) |
| @@ -1264,11 +1264,13 @@ static void end_sync_write(struct bio *bio, int error) | |||
| 1264 | 1264 | ||
| 1265 | update_head_pos(i, r10_bio); | 1265 | update_head_pos(i, r10_bio); |
| 1266 | 1266 | ||
| 1267 | rdev_dec_pending(conf->mirrors[d].rdev, mddev); | ||
| 1267 | while (atomic_dec_and_test(&r10_bio->remaining)) { | 1268 | while (atomic_dec_and_test(&r10_bio->remaining)) { |
| 1268 | if (r10_bio->master_bio == NULL) { | 1269 | if (r10_bio->master_bio == NULL) { |
| 1269 | /* the primary of several recovery bios */ | 1270 | /* the primary of several recovery bios */ |
| 1270 | md_done_sync(mddev, r10_bio->sectors, 1); | 1271 | sector_t s = r10_bio->sectors; |
| 1271 | put_buf(r10_bio); | 1272 | put_buf(r10_bio); |
| 1273 | md_done_sync(mddev, s, 1); | ||
| 1272 | break; | 1274 | break; |
| 1273 | } else { | 1275 | } else { |
| 1274 | r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; | 1276 | r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; |
| @@ -1276,7 +1278,6 @@ static void end_sync_write(struct bio *bio, int error) | |||
| 1276 | r10_bio = r10_bio2; | 1278 | r10_bio = r10_bio2; |
| 1277 | } | 1279 | } |
| 1278 | } | 1280 | } |
| 1279 | rdev_dec_pending(conf->mirrors[d].rdev, mddev); | ||
| 1280 | } | 1281 | } |
| 1281 | 1282 | ||
| 1282 | /* | 1283 | /* |
| @@ -1749,8 +1750,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1749 | if (!go_faster && conf->nr_waiting) | 1750 | if (!go_faster && conf->nr_waiting) |
| 1750 | msleep_interruptible(1000); | 1751 | msleep_interruptible(1000); |
| 1751 | 1752 | ||
| 1752 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
| 1753 | |||
| 1754 | /* Again, very different code for resync and recovery. | 1753 | /* Again, very different code for resync and recovery. |
| 1755 | * Both must result in an r10bio with a list of bios that | 1754 | * Both must result in an r10bio with a list of bios that |
| 1756 | * have bi_end_io, bi_sector, bi_bdev set, | 1755 | * have bi_end_io, bi_sector, bi_bdev set, |
| @@ -1886,6 +1885,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1886 | /* resync. Schedule a read for every block at this virt offset */ | 1885 | /* resync. Schedule a read for every block at this virt offset */ |
| 1887 | int count = 0; | 1886 | int count = 0; |
| 1888 | 1887 | ||
| 1888 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
| 1889 | |||
| 1889 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, | 1890 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, |
| 1890 | &sync_blocks, mddev->degraded) && | 1891 | &sync_blocks, mddev->degraded) && |
| 1891 | !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | 1892 | !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { |
| @@ -2010,13 +2011,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 2010 | /* There is nowhere to write, so all non-sync | 2011 | /* There is nowhere to write, so all non-sync |
| 2011 | * drives must be failed, so try the next chunk... | 2012 | * drives must be failed, so try the next chunk... |
| 2012 | */ | 2013 | */ |
| 2013 | { | 2014 | if (sector_nr + max_sync < max_sector) |
| 2014 | sector_t sec = max_sector - sector_nr; | 2015 | max_sector = sector_nr + max_sync; |
| 2015 | sectors_skipped += sec; | 2016 | |
| 2017 | sectors_skipped += (max_sector - sector_nr); | ||
| 2016 | chunks_skipped ++; | 2018 | chunks_skipped ++; |
| 2017 | sector_nr = max_sector; | 2019 | sector_nr = max_sector; |
| 2018 | goto skipped; | 2020 | goto skipped; |
| 2019 | } | ||
| 2020 | } | 2021 | } |
| 2021 | 2022 | ||
| 2022 | static int run(mddev_t *mddev) | 2023 | static int run(mddev_t *mddev) |
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 40ebde53b3c..b0198691892 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
| @@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters" | |||
| 51 | depends on DVB_CORE && PCI && I2C | 51 | depends on DVB_CORE && PCI && I2C |
| 52 | source "drivers/media/dvb/dm1105/Kconfig" | 52 | source "drivers/media/dvb/dm1105/Kconfig" |
| 53 | 53 | ||
| 54 | comment "Supported FireWire (IEEE 1394) Adapters" | ||
| 55 | depends on DVB_CORE && IEEE1394 | ||
| 56 | source "drivers/media/dvb/firewire/Kconfig" | ||
| 57 | |||
| 54 | comment "Supported DVB Frontends" | 58 | comment "Supported DVB Frontends" |
| 55 | depends on DVB_CORE | 59 | depends on DVB_CORE |
| 56 | source "drivers/media/dvb/frontends/Kconfig" | 60 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index f91e9eb15e5..6092a5bb5a7 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
| @@ -3,3 +3,5 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ | 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ |
| 6 | |||
| 7 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c index b386cc66c6b..451974ba32f 100644 --- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c | |||
| @@ -192,6 +192,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d | |||
| 192 | 192 | ||
| 193 | return 0; | 193 | return 0; |
| 194 | } | 194 | } |
| 195 | EXPORT_SYMBOL(flexcop_pid_feed_control); | ||
| 195 | 196 | ||
| 196 | void flexcop_hw_filter_init(struct flexcop_device *fc) | 197 | void flexcop_hw_filter_init(struct flexcop_device *fc) |
| 197 | { | 198 | { |
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 5b30dfc7846..76e37fd96bb 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c | |||
| @@ -13,9 +13,9 @@ static int enable_pid_filtering = 1; | |||
| 13 | module_param(enable_pid_filtering, int, 0444); | 13 | module_param(enable_pid_filtering, int, 0444); |
| 14 | MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); | 14 | MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); |
| 15 | 15 | ||
| 16 | static int irq_chk_intv; | 16 | static int irq_chk_intv = 100; |
| 17 | module_param(irq_chk_intv, int, 0644); | 17 | module_param(irq_chk_intv, int, 0644); |
| 18 | MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); | 18 | MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); |
| 19 | 19 | ||
| 20 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | 20 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG |
| 21 | #define dprintk(level,args...) \ | 21 | #define dprintk(level,args...) \ |
| @@ -34,7 +34,9 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus | |||
| 34 | 34 | ||
| 35 | static int debug; | 35 | static int debug; |
| 36 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
| 37 | MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); | 37 | MODULE_PARM_DESC(debug, |
| 38 | "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." | ||
| 39 | DEBSTATUS); | ||
| 38 | 40 | ||
| 39 | #define DRIVER_VERSION "0.1" | 41 | #define DRIVER_VERSION "0.1" |
| 40 | #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" | 42 | #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" |
| @@ -58,6 +60,8 @@ struct flexcop_pci { | |||
| 58 | int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ | 60 | int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ |
| 59 | u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ | 61 | u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ |
| 60 | int count; | 62 | int count; |
| 63 | int count_prev; | ||
| 64 | int stream_problem; | ||
| 61 | 65 | ||
| 62 | spinlock_t irq_lock; | 66 | spinlock_t irq_lock; |
| 63 | 67 | ||
| @@ -103,18 +107,32 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) | |||
| 103 | container_of(work, struct flexcop_pci, irq_check_work.work); | 107 | container_of(work, struct flexcop_pci, irq_check_work.work); |
| 104 | struct flexcop_device *fc = fc_pci->fc_dev; | 108 | struct flexcop_device *fc = fc_pci->fc_dev; |
| 105 | 109 | ||
| 106 | flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); | 110 | if (fc->feedcount) { |
| 107 | 111 | ||
| 108 | flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); | 112 | if (fc_pci->count == fc_pci->count_prev) { |
| 109 | 113 | deb_chk("no IRQ since the last check\n"); | |
| 110 | if (v.sram_dest_reg_714.net_ovflow_error) | 114 | if (fc_pci->stream_problem++ == 3) { |
| 111 | deb_chk("sram net_ovflow_error\n"); | 115 | struct dvb_demux_feed *feed; |
| 112 | if (v.sram_dest_reg_714.media_ovflow_error) | 116 | |
| 113 | deb_chk("sram media_ovflow_error\n"); | 117 | spin_lock_irq(&fc->demux.lock); |
| 114 | if (v.sram_dest_reg_714.cai_ovflow_error) | 118 | list_for_each_entry(feed, &fc->demux.feed_list, |
| 115 | deb_chk("sram cai_ovflow_error\n"); | 119 | list_head) { |
| 116 | if (v.sram_dest_reg_714.cai_ovflow_error) | 120 | flexcop_pid_feed_control(fc, feed, 0); |
| 117 | deb_chk("sram cai_ovflow_error\n"); | 121 | } |
| 122 | |||
| 123 | list_for_each_entry(feed, &fc->demux.feed_list, | ||
| 124 | list_head) { | ||
| 125 | flexcop_pid_feed_control(fc, feed, 1); | ||
| 126 | } | ||
| 127 | spin_unlock_irq(&fc->demux.lock); | ||
| 128 | |||
| 129 | fc_pci->stream_problem = 0; | ||
| 130 | } | ||
| 131 | } else { | ||
| 132 | fc_pci->stream_problem = 0; | ||
| 133 | fc_pci->count_prev = fc_pci->count; | ||
| 134 | } | ||
| 135 | } | ||
| 118 | 136 | ||
| 119 | schedule_delayed_work(&fc_pci->irq_check_work, | 137 | schedule_delayed_work(&fc_pci->irq_check_work, |
| 120 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | 138 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); |
| @@ -216,16 +234,12 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) | |||
| 216 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); | 234 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); |
| 217 | deb_irq("IRQ enabled\n"); | 235 | deb_irq("IRQ enabled\n"); |
| 218 | 236 | ||
| 237 | fc_pci->count_prev = fc_pci->count; | ||
| 238 | |||
| 219 | // fc_pci->active_dma1_addr = 0; | 239 | // fc_pci->active_dma1_addr = 0; |
| 220 | // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); | 240 | // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); |
| 221 | 241 | ||
| 222 | if (irq_chk_intv > 0) | ||
| 223 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
| 224 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | ||
| 225 | } else { | 242 | } else { |
| 226 | if (irq_chk_intv > 0) | ||
| 227 | cancel_delayed_work(&fc_pci->irq_check_work); | ||
| 228 | |||
| 229 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); | 243 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); |
| 230 | deb_irq("IRQ disabled\n"); | 244 | deb_irq("IRQ disabled\n"); |
| 231 | 245 | ||
| @@ -299,8 +313,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) | |||
| 299 | IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) | 313 | IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) |
| 300 | goto err_pci_iounmap; | 314 | goto err_pci_iounmap; |
| 301 | 315 | ||
| 302 | |||
| 303 | |||
| 304 | fc_pci->init_state |= FC_PCI_INIT; | 316 | fc_pci->init_state |= FC_PCI_INIT; |
| 305 | return ret; | 317 | return ret; |
| 306 | 318 | ||
| @@ -375,6 +387,10 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
| 375 | 387 | ||
| 376 | INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); | 388 | INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); |
| 377 | 389 | ||
| 390 | if (irq_chk_intv > 0) | ||
| 391 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
| 392 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | ||
| 393 | |||
| 378 | return ret; | 394 | return ret; |
| 379 | 395 | ||
| 380 | err_fc_exit: | 396 | err_fc_exit: |
| @@ -393,6 +409,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev) | |||
| 393 | { | 409 | { |
| 394 | struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); | 410 | struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); |
| 395 | 411 | ||
| 412 | if (irq_chk_intv > 0) | ||
| 413 | cancel_delayed_work(&fc_pci->irq_check_work); | ||
| 414 | |||
| 396 | flexcop_pci_dma_exit(fc_pci); | 415 | flexcop_pci_dma_exit(fc_pci); |
| 397 | flexcop_device_exit(fc_pci->fc_dev); | 416 | flexcop_device_exit(fc_pci->fc_dev); |
| 398 | flexcop_pci_exit(fc_pci); | 417 | flexcop_pci_exit(fc_pci); |
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 676413a915b..91068952b50 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c | |||
| @@ -212,8 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc) | |||
| 212 | v210.sw_reset_210.Block_reset_enable = 0xb2; | 212 | v210.sw_reset_210.Block_reset_enable = 0xb2; |
| 213 | 213 | ||
| 214 | fc->write_ibi_reg(fc,sw_reset_210,v210); | 214 | fc->write_ibi_reg(fc,sw_reset_210,v210); |
| 215 | msleep(1); | 215 | udelay(1000); |
| 216 | |||
| 217 | fc->write_ibi_reg(fc,ctrl_208,v208_save); | 216 | fc->write_ibi_reg(fc,ctrl_208,v208_save); |
| 218 | } | 217 | } |
| 219 | 218 | ||
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig new file mode 100644 index 00000000000..69028253e98 --- /dev/null +++ b/drivers/media/dvb/firewire/Kconfig | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | config DVB_FIREDTV | ||
| 2 | tristate "FireDTV and FloppyDTV" | ||
| 3 | depends on DVB_CORE && IEEE1394 | ||
| 4 | help | ||
| 5 | Support for DVB receivers from Digital Everywhere | ||
| 6 | which are connected via IEEE 1394 (FireWire). | ||
| 7 | |||
| 8 | These devices don't have an MPEG decoder built in, | ||
| 9 | so you need an external software decoder to watch TV. | ||
| 10 | |||
| 11 | To compile this driver as a module, say M here: | ||
| 12 | the module will be called firedtv. | ||
| 13 | |||
| 14 | if DVB_FIREDTV | ||
| 15 | |||
| 16 | config DVB_FIREDTV_IEEE1394 | ||
| 17 | def_bool IEEE1394 | ||
| 18 | |||
| 19 | config DVB_FIREDTV_INPUT | ||
| 20 | def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m) | ||
| 21 | |||
| 22 | endif # DVB_FIREDTV | ||
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile new file mode 100644 index 00000000000..2034695ba19 --- /dev/null +++ b/drivers/media/dvb/firewire/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | obj-$(CONFIG_DVB_FIREDTV) += firedtv.o | ||
| 2 | |||
| 3 | firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o | ||
| 4 | firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o | ||
| 5 | firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o | ||
| 6 | |||
| 7 | ccflags-y += -Idrivers/media/dvb/dvb-core | ||
| 8 | ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394 | ||
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c new file mode 100644 index 00000000000..4e207658c5d --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-1394.c | |||
| @@ -0,0 +1,285 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com> | ||
| 6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation; either version 2 of | ||
| 11 | * the License, or (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/list.h> | ||
| 18 | #include <linux/spinlock.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | |||
| 21 | #include <dma.h> | ||
| 22 | #include <csr1212.h> | ||
| 23 | #include <highlevel.h> | ||
| 24 | #include <hosts.h> | ||
| 25 | #include <ieee1394.h> | ||
| 26 | #include <iso.h> | ||
| 27 | #include <nodemgr.h> | ||
| 28 | |||
| 29 | #include "firedtv.h" | ||
| 30 | |||
| 31 | static LIST_HEAD(node_list); | ||
| 32 | static DEFINE_SPINLOCK(node_list_lock); | ||
| 33 | |||
| 34 | #define FIREWIRE_HEADER_SIZE 4 | ||
| 35 | #define CIP_HEADER_SIZE 8 | ||
| 36 | |||
| 37 | static void rawiso_activity_cb(struct hpsb_iso *iso) | ||
| 38 | { | ||
| 39 | struct firedtv *f, *fdtv = NULL; | ||
| 40 | unsigned int i, num, packet; | ||
| 41 | unsigned char *buf; | ||
| 42 | unsigned long flags; | ||
| 43 | int count; | ||
| 44 | |||
| 45 | spin_lock_irqsave(&node_list_lock, flags); | ||
| 46 | list_for_each_entry(f, &node_list, list) | ||
| 47 | if (f->backend_data == iso) { | ||
| 48 | fdtv = f; | ||
| 49 | break; | ||
| 50 | } | ||
| 51 | spin_unlock_irqrestore(&node_list_lock, flags); | ||
| 52 | |||
| 53 | packet = iso->first_packet; | ||
| 54 | num = hpsb_iso_n_ready(iso); | ||
| 55 | |||
| 56 | if (!fdtv) { | ||
| 57 | dev_err(fdtv->device, "received at unknown iso channel\n"); | ||
| 58 | goto out; | ||
| 59 | } | ||
| 60 | |||
| 61 | for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) { | ||
| 62 | buf = dma_region_i(&iso->data_buf, unsigned char, | ||
| 63 | iso->infos[packet].offset + CIP_HEADER_SIZE); | ||
| 64 | count = (iso->infos[packet].len - CIP_HEADER_SIZE) / | ||
| 65 | (188 + FIREWIRE_HEADER_SIZE); | ||
| 66 | |||
| 67 | /* ignore empty packet */ | ||
| 68 | if (iso->infos[packet].len <= CIP_HEADER_SIZE) | ||
| 69 | continue; | ||
| 70 | |||
| 71 | while (count--) { | ||
| 72 | if (buf[FIREWIRE_HEADER_SIZE] == 0x47) | ||
| 73 | dvb_dmx_swfilter_packets(&fdtv->demux, | ||
| 74 | &buf[FIREWIRE_HEADER_SIZE], 1); | ||
| 75 | else | ||
| 76 | dev_err(fdtv->device, | ||
| 77 | "skipping invalid packet\n"); | ||
| 78 | buf += 188 + FIREWIRE_HEADER_SIZE; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | out: | ||
| 82 | hpsb_iso_recv_release_packets(iso, num); | ||
| 83 | } | ||
| 84 | |||
| 85 | static inline struct node_entry *node_of(struct firedtv *fdtv) | ||
| 86 | { | ||
| 87 | return container_of(fdtv->device, struct unit_directory, device)->ne; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg) | ||
| 91 | { | ||
| 92 | return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data, | ||
| 93 | (__force quadlet_t)arg); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) | ||
| 97 | { | ||
| 98 | return hpsb_node_read(node_of(fdtv), addr, data, len); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) | ||
| 102 | { | ||
| 103 | return hpsb_node_write(node_of(fdtv), addr, data, len); | ||
| 104 | } | ||
| 105 | |||
| 106 | #define FDTV_ISO_BUFFER_PACKETS 256 | ||
| 107 | #define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200) | ||
| 108 | |||
| 109 | static int start_iso(struct firedtv *fdtv) | ||
| 110 | { | ||
| 111 | struct hpsb_iso *iso_handle; | ||
| 112 | int ret; | ||
| 113 | |||
| 114 | iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host, | ||
| 115 | FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS, | ||
| 116 | fdtv->isochannel, HPSB_ISO_DMA_DEFAULT, | ||
| 117 | -1, /* stat.config.irq_interval */ | ||
| 118 | rawiso_activity_cb); | ||
| 119 | if (iso_handle == NULL) { | ||
| 120 | dev_err(fdtv->device, "cannot initialize iso receive\n"); | ||
| 121 | return -ENOMEM; | ||
| 122 | } | ||
| 123 | fdtv->backend_data = iso_handle; | ||
| 124 | |||
| 125 | ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0); | ||
| 126 | if (ret != 0) { | ||
| 127 | dev_err(fdtv->device, "cannot start iso receive\n"); | ||
| 128 | hpsb_iso_shutdown(iso_handle); | ||
| 129 | fdtv->backend_data = NULL; | ||
| 130 | } | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static void stop_iso(struct firedtv *fdtv) | ||
| 135 | { | ||
| 136 | struct hpsb_iso *iso_handle = fdtv->backend_data; | ||
| 137 | |||
| 138 | if (iso_handle != NULL) { | ||
| 139 | hpsb_iso_stop(iso_handle); | ||
| 140 | hpsb_iso_shutdown(iso_handle); | ||
| 141 | } | ||
| 142 | fdtv->backend_data = NULL; | ||
| 143 | } | ||
| 144 | |||
| 145 | static const struct firedtv_backend fdtv_1394_backend = { | ||
| 146 | .lock = node_lock, | ||
| 147 | .read = node_read, | ||
| 148 | .write = node_write, | ||
| 149 | .start_iso = start_iso, | ||
| 150 | .stop_iso = stop_iso, | ||
| 151 | }; | ||
| 152 | |||
| 153 | static void fcp_request(struct hpsb_host *host, int nodeid, int direction, | ||
| 154 | int cts, u8 *data, size_t length) | ||
| 155 | { | ||
| 156 | struct firedtv *f, *fdtv = NULL; | ||
| 157 | unsigned long flags; | ||
| 158 | int su; | ||
| 159 | |||
| 160 | if (length == 0 || (data[0] & 0xf0) != 0) | ||
| 161 | return; | ||
| 162 | |||
| 163 | su = data[1] & 0x7; | ||
| 164 | |||
| 165 | spin_lock_irqsave(&node_list_lock, flags); | ||
| 166 | list_for_each_entry(f, &node_list, list) | ||
| 167 | if (node_of(f)->host == host && | ||
| 168 | node_of(f)->nodeid == nodeid && | ||
| 169 | (f->subunit == su || (f->subunit == 0 && su == 0x7))) { | ||
| 170 | fdtv = f; | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | spin_unlock_irqrestore(&node_list_lock, flags); | ||
| 174 | |||
| 175 | if (fdtv) | ||
| 176 | avc_recv(fdtv, data, length); | ||
| 177 | } | ||
| 178 | |||
| 179 | static int node_probe(struct device *dev) | ||
| 180 | { | ||
| 181 | struct unit_directory *ud = | ||
| 182 | container_of(dev, struct unit_directory, device); | ||
| 183 | struct firedtv *fdtv; | ||
| 184 | int kv_len, err; | ||
| 185 | void *kv_str; | ||
| 186 | |||
| 187 | kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); | ||
| 188 | kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); | ||
| 189 | |||
| 190 | fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); | ||
| 191 | if (!fdtv) | ||
| 192 | return -ENOMEM; | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Work around a bug in udev's path_id script: Use the fw-host's dev | ||
| 196 | * instead of the unit directory's dev as parent of the input device. | ||
| 197 | */ | ||
| 198 | err = fdtv_register_rc(fdtv, dev->parent->parent); | ||
| 199 | if (err) | ||
| 200 | goto fail_free; | ||
| 201 | |||
| 202 | spin_lock_irq(&node_list_lock); | ||
| 203 | list_add_tail(&fdtv->list, &node_list); | ||
| 204 | spin_unlock_irq(&node_list_lock); | ||
| 205 | |||
| 206 | err = avc_identify_subunit(fdtv); | ||
| 207 | if (err) | ||
| 208 | goto fail; | ||
| 209 | |||
| 210 | err = fdtv_dvb_register(fdtv); | ||
| 211 | if (err) | ||
| 212 | goto fail; | ||
| 213 | |||
| 214 | avc_register_remote_control(fdtv); | ||
| 215 | return 0; | ||
| 216 | fail: | ||
| 217 | spin_lock_irq(&node_list_lock); | ||
| 218 | list_del(&fdtv->list); | ||
| 219 | spin_unlock_irq(&node_list_lock); | ||
| 220 | fdtv_unregister_rc(fdtv); | ||
| 221 | fail_free: | ||
| 222 | kfree(fdtv); | ||
| 223 | return err; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int node_remove(struct device *dev) | ||
| 227 | { | ||
| 228 | struct firedtv *fdtv = dev->driver_data; | ||
| 229 | |||
| 230 | fdtv_dvb_unregister(fdtv); | ||
| 231 | |||
| 232 | spin_lock_irq(&node_list_lock); | ||
| 233 | list_del(&fdtv->list); | ||
| 234 | spin_unlock_irq(&node_list_lock); | ||
| 235 | |||
| 236 | cancel_work_sync(&fdtv->remote_ctrl_work); | ||
| 237 | fdtv_unregister_rc(fdtv); | ||
| 238 | |||
| 239 | kfree(fdtv); | ||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int node_update(struct unit_directory *ud) | ||
| 244 | { | ||
| 245 | struct firedtv *fdtv = ud->device.driver_data; | ||
| 246 | |||
| 247 | if (fdtv->isochannel >= 0) | ||
| 248 | cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
| 249 | fdtv->isochannel); | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static struct hpsb_protocol_driver fdtv_driver = { | ||
| 254 | .name = "firedtv", | ||
| 255 | .update = node_update, | ||
| 256 | .driver = { | ||
| 257 | .probe = node_probe, | ||
| 258 | .remove = node_remove, | ||
| 259 | }, | ||
| 260 | }; | ||
| 261 | |||
| 262 | static struct hpsb_highlevel fdtv_highlevel = { | ||
| 263 | .name = "firedtv", | ||
| 264 | .fcp_request = fcp_request, | ||
| 265 | }; | ||
| 266 | |||
| 267 | int __init fdtv_1394_init(struct ieee1394_device_id id_table[]) | ||
| 268 | { | ||
| 269 | int ret; | ||
| 270 | |||
| 271 | hpsb_register_highlevel(&fdtv_highlevel); | ||
| 272 | fdtv_driver.id_table = id_table; | ||
| 273 | ret = hpsb_register_protocol(&fdtv_driver); | ||
| 274 | if (ret) { | ||
| 275 | printk(KERN_ERR "firedtv: failed to register protocol\n"); | ||
| 276 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
| 277 | } | ||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | |||
| 281 | void __exit fdtv_1394_exit(void) | ||
| 282 | { | ||
| 283 | hpsb_unregister_protocol(&fdtv_driver); | ||
| 284 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
| 285 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c new file mode 100644 index 00000000000..b55d9ccaf33 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-avc.c | |||
| @@ -0,0 +1,1315 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2008 Ben Backx <ben@bbackx.com> | ||
| 6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation; either version 2 of | ||
| 11 | * the License, or (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/bug.h> | ||
| 15 | #include <linux/crc32.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/moduleparam.h> | ||
| 21 | #include <linux/mutex.h> | ||
| 22 | #include <linux/string.h> | ||
| 23 | #include <linux/stringify.h> | ||
| 24 | #include <linux/wait.h> | ||
| 25 | #include <linux/workqueue.h> | ||
| 26 | |||
| 27 | #include "firedtv.h" | ||
| 28 | |||
| 29 | #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL | ||
| 30 | |||
| 31 | #define AVC_CTYPE_CONTROL 0x0 | ||
| 32 | #define AVC_CTYPE_STATUS 0x1 | ||
| 33 | #define AVC_CTYPE_NOTIFY 0x3 | ||
| 34 | |||
| 35 | #define AVC_RESPONSE_ACCEPTED 0x9 | ||
| 36 | #define AVC_RESPONSE_STABLE 0xc | ||
| 37 | #define AVC_RESPONSE_CHANGED 0xd | ||
| 38 | #define AVC_RESPONSE_INTERIM 0xf | ||
| 39 | |||
| 40 | #define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3) | ||
| 41 | #define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3) | ||
| 42 | |||
| 43 | #define AVC_OPCODE_VENDOR 0x00 | ||
| 44 | #define AVC_OPCODE_READ_DESCRIPTOR 0x09 | ||
| 45 | #define AVC_OPCODE_DSIT 0xc8 | ||
| 46 | #define AVC_OPCODE_DSD 0xcb | ||
| 47 | |||
| 48 | #define DESCRIPTOR_TUNER_STATUS 0x80 | ||
| 49 | #define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00 | ||
| 50 | |||
| 51 | #define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */ | ||
| 52 | #define SFE_VENDOR_DE_COMPANYID_1 0x12 | ||
| 53 | #define SFE_VENDOR_DE_COMPANYID_2 0x87 | ||
| 54 | |||
| 55 | #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a | ||
| 56 | #define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52 | ||
| 57 | #define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */ | ||
| 58 | |||
| 59 | #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00 | ||
| 60 | #define SFE_VENDOR_OPCODE_HOST2CA 0x56 | ||
| 61 | #define SFE_VENDOR_OPCODE_CA2HOST 0x57 | ||
| 62 | #define SFE_VENDOR_OPCODE_CISTATUS 0x59 | ||
| 63 | #define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */ | ||
| 64 | |||
| 65 | #define SFE_VENDOR_TAG_CA_RESET 0x00 | ||
| 66 | #define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01 | ||
| 67 | #define SFE_VENDOR_TAG_CA_PMT 0x02 | ||
| 68 | #define SFE_VENDOR_TAG_CA_DATE_TIME 0x04 | ||
| 69 | #define SFE_VENDOR_TAG_CA_MMI 0x05 | ||
| 70 | #define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07 | ||
| 71 | |||
| 72 | #define EN50221_LIST_MANAGEMENT_ONLY 0x03 | ||
| 73 | #define EN50221_TAG_APP_INFO 0x9f8021 | ||
| 74 | #define EN50221_TAG_CA_INFO 0x9f8031 | ||
| 75 | |||
| 76 | struct avc_command_frame { | ||
| 77 | int length; | ||
| 78 | u8 ctype; | ||
| 79 | u8 subunit; | ||
| 80 | u8 opcode; | ||
| 81 | u8 operand[509]; | ||
| 82 | }; | ||
| 83 | |||
| 84 | struct avc_response_frame { | ||
| 85 | int length; | ||
| 86 | u8 response; | ||
| 87 | u8 subunit; | ||
| 88 | u8 opcode; | ||
| 89 | u8 operand[509]; | ||
| 90 | }; | ||
| 91 | |||
| 92 | #define AVC_DEBUG_FCP_SUBACTIONS 1 | ||
| 93 | #define AVC_DEBUG_FCP_PAYLOADS 2 | ||
| 94 | |||
| 95 | static int avc_debug; | ||
| 96 | module_param_named(debug, avc_debug, int, 0644); | ||
| 97 | MODULE_PARM_DESC(debug, "Verbose logging (default = 0" | ||
| 98 | ", FCP subactions = " __stringify(AVC_DEBUG_FCP_SUBACTIONS) | ||
| 99 | ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS) | ||
| 100 | ", or all = -1)"); | ||
| 101 | |||
| 102 | static const char *debug_fcp_ctype(unsigned int ctype) | ||
| 103 | { | ||
| 104 | static const char *ctypes[] = { | ||
| 105 | [0x0] = "CONTROL", [0x1] = "STATUS", | ||
| 106 | [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY", | ||
| 107 | [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED", | ||
| 108 | [0x9] = "ACCEPTED", [0xa] = "REJECTED", | ||
| 109 | [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE", | ||
| 110 | [0xd] = "CHANGED", [0xf] = "INTERIM", | ||
| 111 | }; | ||
| 112 | const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL; | ||
| 113 | |||
| 114 | return ret ? ret : "?"; | ||
| 115 | } | ||
| 116 | |||
| 117 | static const char *debug_fcp_opcode(unsigned int opcode, | ||
| 118 | const u8 *data, size_t length) | ||
| 119 | { | ||
| 120 | switch (opcode) { | ||
| 121 | case AVC_OPCODE_VENDOR: break; | ||
| 122 | case AVC_OPCODE_READ_DESCRIPTOR: return "ReadDescriptor"; | ||
| 123 | case AVC_OPCODE_DSIT: return "DirectSelectInfo.Type"; | ||
| 124 | case AVC_OPCODE_DSD: return "DirectSelectData"; | ||
| 125 | default: return "?"; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (length < 7 || | ||
| 129 | data[3] != SFE_VENDOR_DE_COMPANYID_0 || | ||
| 130 | data[4] != SFE_VENDOR_DE_COMPANYID_1 || | ||
| 131 | data[5] != SFE_VENDOR_DE_COMPANYID_2) | ||
| 132 | return "Vendor"; | ||
| 133 | |||
| 134 | switch (data[6]) { | ||
| 135 | case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; | ||
| 136 | case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; | ||
| 137 | case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; | ||
| 138 | case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; | ||
| 139 | case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; | ||
| 140 | } | ||
| 141 | return "Vendor"; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void debug_fcp(const u8 *data, size_t length) | ||
| 145 | { | ||
| 146 | unsigned int subunit_type, subunit_id, op; | ||
| 147 | const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; | ||
| 148 | |||
| 149 | if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) { | ||
| 150 | subunit_type = data[1] >> 3; | ||
| 151 | subunit_id = data[1] & 7; | ||
| 152 | op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; | ||
| 153 | printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", | ||
| 154 | prefix, subunit_type, subunit_id, length, | ||
| 155 | debug_fcp_ctype(data[0]), | ||
| 156 | debug_fcp_opcode(op, data, length)); | ||
| 157 | } | ||
| 158 | |||
| 159 | if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) | ||
| 160 | print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, | ||
| 161 | data, length, false); | ||
| 162 | } | ||
| 163 | |||
| 164 | static int __avc_write(struct firedtv *fdtv, | ||
| 165 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
| 166 | { | ||
| 167 | int err, retry; | ||
| 168 | |||
| 169 | if (r) | ||
| 170 | fdtv->avc_reply_received = false; | ||
| 171 | |||
| 172 | for (retry = 0; retry < 6; retry++) { | ||
| 173 | if (unlikely(avc_debug)) | ||
| 174 | debug_fcp(&c->ctype, c->length); | ||
| 175 | |||
| 176 | err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, | ||
| 177 | (void *)&c->ctype, c->length); | ||
| 178 | if (err) { | ||
| 179 | fdtv->avc_reply_received = true; | ||
| 180 | dev_err(fdtv->device, "FCP command write failed\n"); | ||
| 181 | return err; | ||
| 182 | } | ||
| 183 | |||
| 184 | if (!r) | ||
| 185 | return 0; | ||
| 186 | |||
| 187 | /* | ||
| 188 | * AV/C specs say that answers should be sent within 150 ms. | ||
| 189 | * Time out after 200 ms. | ||
| 190 | */ | ||
| 191 | if (wait_event_timeout(fdtv->avc_wait, | ||
| 192 | fdtv->avc_reply_received, | ||
| 193 | msecs_to_jiffies(200)) != 0) { | ||
| 194 | r->length = fdtv->response_length; | ||
| 195 | memcpy(&r->response, fdtv->response, r->length); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | dev_err(fdtv->device, "FCP response timed out\n"); | ||
| 201 | return -ETIMEDOUT; | ||
| 202 | } | ||
| 203 | |||
| 204 | static int avc_write(struct firedtv *fdtv, | ||
| 205 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
| 206 | { | ||
| 207 | int ret; | ||
| 208 | |||
| 209 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
| 210 | return -EINTR; | ||
| 211 | |||
| 212 | ret = __avc_write(fdtv, c, r); | ||
| 213 | |||
| 214 | mutex_unlock(&fdtv->avc_mutex); | ||
| 215 | return ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | int avc_recv(struct firedtv *fdtv, void *data, size_t length) | ||
| 219 | { | ||
| 220 | struct avc_response_frame *r = | ||
| 221 | data - offsetof(struct avc_response_frame, response); | ||
| 222 | |||
| 223 | if (unlikely(avc_debug)) | ||
| 224 | debug_fcp(data, length); | ||
| 225 | |||
| 226 | if (length >= 8 && | ||
| 227 | r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && | ||
| 228 | r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && | ||
| 229 | r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && | ||
| 230 | r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { | ||
| 231 | if (r->response == AVC_RESPONSE_CHANGED) { | ||
| 232 | fdtv_handle_rc(fdtv, | ||
| 233 | r->operand[4] << 8 | r->operand[5]); | ||
| 234 | schedule_work(&fdtv->remote_ctrl_work); | ||
| 235 | } else if (r->response != AVC_RESPONSE_INTERIM) { | ||
| 236 | dev_info(fdtv->device, | ||
| 237 | "remote control result = %d\n", r->response); | ||
| 238 | } | ||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | if (fdtv->avc_reply_received) { | ||
| 243 | dev_err(fdtv->device, "out-of-order AVC response, ignored\n"); | ||
| 244 | return -EIO; | ||
| 245 | } | ||
| 246 | |||
| 247 | memcpy(fdtv->response, data, length); | ||
| 248 | fdtv->response_length = length; | ||
| 249 | |||
| 250 | fdtv->avc_reply_received = true; | ||
| 251 | wake_up(&fdtv->avc_wait); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | /* | ||
| 257 | * tuning command for setting the relative LNB frequency | ||
| 258 | * (not supported by the AVC standard) | ||
| 259 | */ | ||
| 260 | static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | ||
| 261 | struct dvb_frontend_parameters *params, | ||
| 262 | struct avc_command_frame *c) | ||
| 263 | { | ||
| 264 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 265 | |||
| 266 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 267 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 268 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 269 | c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; | ||
| 270 | |||
| 271 | c->operand[4] = (params->frequency >> 24) & 0xff; | ||
| 272 | c->operand[5] = (params->frequency >> 16) & 0xff; | ||
| 273 | c->operand[6] = (params->frequency >> 8) & 0xff; | ||
| 274 | c->operand[7] = params->frequency & 0xff; | ||
| 275 | |||
| 276 | c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff; | ||
| 277 | c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff; | ||
| 278 | |||
| 279 | switch (params->u.qpsk.fec_inner) { | ||
| 280 | case FEC_1_2: c->operand[10] = 0x1; break; | ||
| 281 | case FEC_2_3: c->operand[10] = 0x2; break; | ||
| 282 | case FEC_3_4: c->operand[10] = 0x3; break; | ||
| 283 | case FEC_5_6: c->operand[10] = 0x4; break; | ||
| 284 | case FEC_7_8: c->operand[10] = 0x5; break; | ||
| 285 | case FEC_4_5: | ||
| 286 | case FEC_8_9: | ||
| 287 | case FEC_AUTO: | ||
| 288 | default: c->operand[10] = 0x0; | ||
| 289 | } | ||
| 290 | |||
| 291 | if (fdtv->voltage == 0xff) | ||
| 292 | c->operand[11] = 0xff; | ||
| 293 | else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */ | ||
| 294 | c->operand[11] = 0; | ||
| 295 | else | ||
| 296 | c->operand[11] = 1; | ||
| 297 | |||
| 298 | if (fdtv->tone == 0xff) | ||
| 299 | c->operand[12] = 0xff; | ||
| 300 | else if (fdtv->tone == SEC_TONE_ON) /* band */ | ||
| 301 | c->operand[12] = 1; | ||
| 302 | else | ||
| 303 | c->operand[12] = 0; | ||
| 304 | |||
| 305 | if (fdtv->type == FIREDTV_DVB_S2) { | ||
| 306 | c->operand[13] = 0x1; | ||
| 307 | c->operand[14] = 0xff; | ||
| 308 | c->operand[15] = 0xff; | ||
| 309 | c->length = 20; | ||
| 310 | } else { | ||
| 311 | c->length = 16; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, | ||
| 316 | struct avc_command_frame *c) | ||
| 317 | { | ||
| 318 | c->opcode = AVC_OPCODE_DSD; | ||
| 319 | |||
| 320 | c->operand[0] = 0; /* source plug */ | ||
| 321 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
| 322 | c->operand[2] = 0x20; /* system id = DVB */ | ||
| 323 | c->operand[3] = 0x00; /* antenna number */ | ||
| 324 | c->operand[4] = 0x11; /* system_specific_multiplex selection_length */ | ||
| 325 | |||
| 326 | /* multiplex_valid_flags, high byte */ | ||
| 327 | c->operand[5] = 0 << 7 /* reserved */ | ||
| 328 | | 0 << 6 /* Polarisation */ | ||
| 329 | | 0 << 5 /* Orbital_Pos */ | ||
| 330 | | 1 << 4 /* Frequency */ | ||
| 331 | | 1 << 3 /* Symbol_Rate */ | ||
| 332 | | 0 << 2 /* FEC_outer */ | ||
| 333 | | (params->u.qam.fec_inner != FEC_AUTO ? 1 << 1 : 0) | ||
| 334 | | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0); | ||
| 335 | |||
| 336 | /* multiplex_valid_flags, low byte */ | ||
| 337 | c->operand[6] = 0 << 7 /* NetworkID */ | ||
| 338 | | 0 << 0 /* reserved */ ; | ||
| 339 | |||
| 340 | c->operand[7] = 0x00; | ||
| 341 | c->operand[8] = 0x00; | ||
| 342 | c->operand[9] = 0x00; | ||
| 343 | c->operand[10] = 0x00; | ||
| 344 | |||
| 345 | c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6); | ||
| 346 | c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff; | ||
| 347 | c->operand[13] = (params->frequency / 4000) & 0xff; | ||
| 348 | c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff; | ||
| 349 | c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff; | ||
| 350 | c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0; | ||
| 351 | c->operand[17] = 0x00; | ||
| 352 | |||
| 353 | switch (params->u.qpsk.fec_inner) { | ||
| 354 | case FEC_1_2: c->operand[18] = 0x1; break; | ||
| 355 | case FEC_2_3: c->operand[18] = 0x2; break; | ||
| 356 | case FEC_3_4: c->operand[18] = 0x3; break; | ||
| 357 | case FEC_5_6: c->operand[18] = 0x4; break; | ||
| 358 | case FEC_7_8: c->operand[18] = 0x5; break; | ||
| 359 | case FEC_8_9: c->operand[18] = 0x6; break; | ||
| 360 | case FEC_4_5: c->operand[18] = 0x8; break; | ||
| 361 | case FEC_AUTO: | ||
| 362 | default: c->operand[18] = 0x0; | ||
| 363 | } | ||
| 364 | |||
| 365 | switch (params->u.qam.modulation) { | ||
| 366 | case QAM_16: c->operand[19] = 0x08; break; | ||
| 367 | case QAM_32: c->operand[19] = 0x10; break; | ||
| 368 | case QAM_64: c->operand[19] = 0x18; break; | ||
| 369 | case QAM_128: c->operand[19] = 0x20; break; | ||
| 370 | case QAM_256: c->operand[19] = 0x28; break; | ||
| 371 | case QAM_AUTO: | ||
| 372 | default: c->operand[19] = 0x00; | ||
| 373 | } | ||
| 374 | |||
| 375 | c->operand[20] = 0x00; | ||
| 376 | c->operand[21] = 0x00; | ||
| 377 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
| 378 | c->operand[22] = 0x00; | ||
| 379 | |||
| 380 | c->length = 28; | ||
| 381 | } | ||
| 382 | |||
| 383 | static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, | ||
| 384 | struct avc_command_frame *c) | ||
| 385 | { | ||
| 386 | struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; | ||
| 387 | |||
| 388 | c->opcode = AVC_OPCODE_DSD; | ||
| 389 | |||
| 390 | c->operand[0] = 0; /* source plug */ | ||
| 391 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
| 392 | c->operand[2] = 0x20; /* system id = DVB */ | ||
| 393 | c->operand[3] = 0x00; /* antenna number */ | ||
| 394 | c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */ | ||
| 395 | |||
| 396 | /* multiplex_valid_flags, high byte */ | ||
| 397 | c->operand[5] = | ||
| 398 | 0 << 7 /* reserved */ | ||
| 399 | | 1 << 6 /* CenterFrequency */ | ||
| 400 | | (ofdm->bandwidth != BANDWIDTH_AUTO ? 1 << 5 : 0) | ||
| 401 | | (ofdm->constellation != QAM_AUTO ? 1 << 4 : 0) | ||
| 402 | | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0) | ||
| 403 | | (ofdm->code_rate_HP != FEC_AUTO ? 1 << 2 : 0) | ||
| 404 | | (ofdm->code_rate_LP != FEC_AUTO ? 1 << 1 : 0) | ||
| 405 | | (ofdm->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0); | ||
| 406 | |||
| 407 | /* multiplex_valid_flags, low byte */ | ||
| 408 | c->operand[6] = | ||
| 409 | 0 << 7 /* NetworkID */ | ||
| 410 | | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0) | ||
| 411 | | 0 << 5 /* OtherFrequencyFlag */ | ||
| 412 | | 0 << 0 /* reserved */ ; | ||
| 413 | |||
| 414 | c->operand[7] = 0x0; | ||
| 415 | c->operand[8] = (params->frequency / 10) >> 24; | ||
| 416 | c->operand[9] = ((params->frequency / 10) >> 16) & 0xff; | ||
| 417 | c->operand[10] = ((params->frequency / 10) >> 8) & 0xff; | ||
| 418 | c->operand[11] = (params->frequency / 10) & 0xff; | ||
| 419 | |||
| 420 | switch (ofdm->bandwidth) { | ||
| 421 | case BANDWIDTH_7_MHZ: c->operand[12] = 0x20; break; | ||
| 422 | case BANDWIDTH_8_MHZ: | ||
| 423 | case BANDWIDTH_6_MHZ: /* not defined by AVC spec */ | ||
| 424 | case BANDWIDTH_AUTO: | ||
| 425 | default: c->operand[12] = 0x00; | ||
| 426 | } | ||
| 427 | |||
| 428 | switch (ofdm->constellation) { | ||
| 429 | case QAM_16: c->operand[13] = 1 << 6; break; | ||
| 430 | case QAM_64: c->operand[13] = 2 << 6; break; | ||
| 431 | case QPSK: | ||
| 432 | default: c->operand[13] = 0x00; | ||
| 433 | } | ||
| 434 | |||
| 435 | switch (ofdm->hierarchy_information) { | ||
| 436 | case HIERARCHY_1: c->operand[13] |= 1 << 3; break; | ||
| 437 | case HIERARCHY_2: c->operand[13] |= 2 << 3; break; | ||
| 438 | case HIERARCHY_4: c->operand[13] |= 3 << 3; break; | ||
| 439 | case HIERARCHY_AUTO: | ||
| 440 | case HIERARCHY_NONE: | ||
| 441 | default: break; | ||
| 442 | } | ||
| 443 | |||
| 444 | switch (ofdm->code_rate_HP) { | ||
| 445 | case FEC_2_3: c->operand[13] |= 1; break; | ||
| 446 | case FEC_3_4: c->operand[13] |= 2; break; | ||
| 447 | case FEC_5_6: c->operand[13] |= 3; break; | ||
| 448 | case FEC_7_8: c->operand[13] |= 4; break; | ||
| 449 | case FEC_1_2: | ||
| 450 | default: break; | ||
| 451 | } | ||
| 452 | |||
| 453 | switch (ofdm->code_rate_LP) { | ||
| 454 | case FEC_2_3: c->operand[14] = 1 << 5; break; | ||
| 455 | case FEC_3_4: c->operand[14] = 2 << 5; break; | ||
| 456 | case FEC_5_6: c->operand[14] = 3 << 5; break; | ||
| 457 | case FEC_7_8: c->operand[14] = 4 << 5; break; | ||
| 458 | case FEC_1_2: | ||
| 459 | default: c->operand[14] = 0x00; break; | ||
| 460 | } | ||
| 461 | |||
| 462 | switch (ofdm->guard_interval) { | ||
| 463 | case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break; | ||
| 464 | case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break; | ||
| 465 | case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break; | ||
| 466 | case GUARD_INTERVAL_1_32: | ||
| 467 | case GUARD_INTERVAL_AUTO: | ||
| 468 | default: break; | ||
| 469 | } | ||
| 470 | |||
| 471 | switch (ofdm->transmission_mode) { | ||
| 472 | case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break; | ||
| 473 | case TRANSMISSION_MODE_2K: | ||
| 474 | case TRANSMISSION_MODE_AUTO: | ||
| 475 | default: break; | ||
| 476 | } | ||
| 477 | |||
| 478 | c->operand[15] = 0x00; /* network_ID[0] */ | ||
| 479 | c->operand[16] = 0x00; /* network_ID[1] */ | ||
| 480 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
| 481 | c->operand[17] = 0x00; | ||
| 482 | |||
| 483 | c->length = 24; | ||
| 484 | } | ||
| 485 | |||
| 486 | int avc_tuner_dsd(struct firedtv *fdtv, | ||
| 487 | struct dvb_frontend_parameters *params) | ||
| 488 | { | ||
| 489 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 490 | struct avc_command_frame *c = (void *)buffer; | ||
| 491 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 492 | |||
| 493 | memset(c, 0, sizeof(*c)); | ||
| 494 | |||
| 495 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 496 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 497 | |||
| 498 | switch (fdtv->type) { | ||
| 499 | case FIREDTV_DVB_S: | ||
| 500 | case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; | ||
| 501 | case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; | ||
| 502 | case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; | ||
| 503 | default: | ||
| 504 | BUG(); | ||
| 505 | } | ||
| 506 | |||
| 507 | if (avc_write(fdtv, c, r) < 0) | ||
| 508 | return -EIO; | ||
| 509 | |||
| 510 | msleep(500); | ||
| 511 | #if 0 | ||
| 512 | /* FIXME: */ | ||
| 513 | /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ | ||
| 514 | if (status) | ||
| 515 | *status = r->operand[2]; | ||
| 516 | #endif | ||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | |||
| 520 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | ||
| 521 | { | ||
| 522 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 523 | struct avc_command_frame *c = (void *)buffer; | ||
| 524 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 525 | int pos, k; | ||
| 526 | |||
| 527 | if (pidc > 16 && pidc != 0xff) | ||
| 528 | return -EINVAL; | ||
| 529 | |||
| 530 | memset(c, 0, sizeof(*c)); | ||
| 531 | |||
| 532 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 533 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 534 | c->opcode = AVC_OPCODE_DSD; | ||
| 535 | |||
| 536 | c->operand[0] = 0; /* source plug */ | ||
| 537 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
| 538 | c->operand[2] = 0x20; /* system id = DVB */ | ||
| 539 | c->operand[3] = 0x00; /* antenna number */ | ||
| 540 | c->operand[4] = 0x00; /* system_specific_multiplex selection_length */ | ||
| 541 | c->operand[5] = pidc; /* Nr_of_dsd_sel_specs */ | ||
| 542 | |||
| 543 | pos = 6; | ||
| 544 | if (pidc != 0xff) | ||
| 545 | for (k = 0; k < pidc; k++) { | ||
| 546 | c->operand[pos++] = 0x13; /* flowfunction relay */ | ||
| 547 | c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */ | ||
| 548 | c->operand[pos++] = (pid[k] >> 8) & 0x1f; | ||
| 549 | c->operand[pos++] = pid[k] & 0xff; | ||
| 550 | c->operand[pos++] = 0x00; /* tableID */ | ||
| 551 | c->operand[pos++] = 0x00; /* filter_length */ | ||
| 552 | } | ||
| 553 | |||
| 554 | c->length = ALIGN(3 + pos, 4); | ||
| 555 | |||
| 556 | if (avc_write(fdtv, c, r) < 0) | ||
| 557 | return -EIO; | ||
| 558 | |||
| 559 | msleep(50); | ||
| 560 | return 0; | ||
| 561 | } | ||
| 562 | |||
| 563 | int avc_tuner_get_ts(struct firedtv *fdtv) | ||
| 564 | { | ||
| 565 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 566 | struct avc_command_frame *c = (void *)buffer; | ||
| 567 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 568 | int sl; | ||
| 569 | |||
| 570 | memset(c, 0, sizeof(*c)); | ||
| 571 | |||
| 572 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 573 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 574 | c->opcode = AVC_OPCODE_DSIT; | ||
| 575 | |||
| 576 | sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11; | ||
| 577 | |||
| 578 | c->operand[0] = 0; /* source plug */ | ||
| 579 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
| 580 | c->operand[2] = 0xff; /* status */ | ||
| 581 | c->operand[3] = 0x20; /* system id = DVB */ | ||
| 582 | c->operand[4] = 0x00; /* antenna number */ | ||
| 583 | c->operand[5] = 0x0; /* system_specific_search_flags */ | ||
| 584 | c->operand[6] = sl; /* system_specific_multiplex selection_length */ | ||
| 585 | c->operand[7] = 0x00; /* valid_flags [0] */ | ||
| 586 | c->operand[8] = 0x00; /* valid_flags [1] */ | ||
| 587 | c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ | ||
| 588 | |||
| 589 | c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; | ||
| 590 | |||
| 591 | if (avc_write(fdtv, c, r) < 0) | ||
| 592 | return -EIO; | ||
| 593 | |||
| 594 | msleep(250); | ||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | int avc_identify_subunit(struct firedtv *fdtv) | ||
| 599 | { | ||
| 600 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 601 | struct avc_command_frame *c = (void *)buffer; | ||
| 602 | struct avc_response_frame *r = (void *)buffer; | ||
| 603 | |||
| 604 | memset(c, 0, sizeof(*c)); | ||
| 605 | |||
| 606 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 607 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 608 | c->opcode = AVC_OPCODE_READ_DESCRIPTOR; | ||
| 609 | |||
| 610 | c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER; | ||
| 611 | c->operand[1] = 0xff; | ||
| 612 | c->operand[2] = 0x00; | ||
| 613 | c->operand[3] = 0x00; /* length highbyte */ | ||
| 614 | c->operand[4] = 0x08; /* length lowbyte */ | ||
| 615 | c->operand[5] = 0x00; /* offset highbyte */ | ||
| 616 | c->operand[6] = 0x0d; /* offset lowbyte */ | ||
| 617 | |||
| 618 | c->length = 12; | ||
| 619 | |||
| 620 | if (avc_write(fdtv, c, r) < 0) | ||
| 621 | return -EIO; | ||
| 622 | |||
| 623 | if ((r->response != AVC_RESPONSE_STABLE && | ||
| 624 | r->response != AVC_RESPONSE_ACCEPTED) || | ||
| 625 | (r->operand[3] << 8) + r->operand[4] != 8) { | ||
| 626 | dev_err(fdtv->device, "cannot read subunit identifier\n"); | ||
| 627 | return -EINVAL; | ||
| 628 | } | ||
| 629 | return 0; | ||
| 630 | } | ||
| 631 | |||
| 632 | #define SIZEOF_ANTENNA_INPUT_INFO 22 | ||
| 633 | |||
| 634 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | ||
| 635 | { | ||
| 636 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 637 | struct avc_command_frame *c = (void *)buffer; | ||
| 638 | struct avc_response_frame *r = (void *)buffer; | ||
| 639 | int length; | ||
| 640 | |||
| 641 | memset(c, 0, sizeof(*c)); | ||
| 642 | |||
| 643 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 644 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 645 | c->opcode = AVC_OPCODE_READ_DESCRIPTOR; | ||
| 646 | |||
| 647 | c->operand[0] = DESCRIPTOR_TUNER_STATUS; | ||
| 648 | c->operand[1] = 0xff; /* read_result_status */ | ||
| 649 | c->operand[2] = 0x00; /* reserved */ | ||
| 650 | c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */ | ||
| 651 | c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */ | ||
| 652 | c->operand[5] = 0x00; | ||
| 653 | c->operand[6] = 0x00; | ||
| 654 | |||
| 655 | c->length = 12; | ||
| 656 | |||
| 657 | if (avc_write(fdtv, c, r) < 0) | ||
| 658 | return -EIO; | ||
| 659 | |||
| 660 | if (r->response != AVC_RESPONSE_STABLE && | ||
| 661 | r->response != AVC_RESPONSE_ACCEPTED) { | ||
| 662 | dev_err(fdtv->device, "cannot read tuner status\n"); | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | |||
| 666 | length = r->operand[9]; | ||
| 667 | if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { | ||
| 668 | dev_err(fdtv->device, "got invalid tuner status\n"); | ||
| 669 | return -EINVAL; | ||
| 670 | } | ||
| 671 | |||
| 672 | stat->active_system = r->operand[10]; | ||
| 673 | stat->searching = r->operand[11] >> 7 & 1; | ||
| 674 | stat->moving = r->operand[11] >> 6 & 1; | ||
| 675 | stat->no_rf = r->operand[11] >> 5 & 1; | ||
| 676 | stat->input = r->operand[12] >> 7 & 1; | ||
| 677 | stat->selected_antenna = r->operand[12] & 0x7f; | ||
| 678 | stat->ber = r->operand[13] << 24 | | ||
| 679 | r->operand[14] << 16 | | ||
| 680 | r->operand[15] << 8 | | ||
| 681 | r->operand[16]; | ||
| 682 | stat->signal_strength = r->operand[17]; | ||
| 683 | stat->raster_frequency = r->operand[18] >> 6 & 2; | ||
| 684 | stat->rf_frequency = (r->operand[18] & 0x3f) << 16 | | ||
| 685 | r->operand[19] << 8 | | ||
| 686 | r->operand[20]; | ||
| 687 | stat->man_dep_info_length = r->operand[21]; | ||
| 688 | stat->front_end_error = r->operand[22] >> 4 & 1; | ||
| 689 | stat->antenna_error = r->operand[22] >> 3 & 1; | ||
| 690 | stat->front_end_power_status = r->operand[22] >> 1 & 1; | ||
| 691 | stat->power_supply = r->operand[22] & 1; | ||
| 692 | stat->carrier_noise_ratio = r->operand[23] << 8 | | ||
| 693 | r->operand[24]; | ||
| 694 | stat->power_supply_voltage = r->operand[27]; | ||
| 695 | stat->antenna_voltage = r->operand[28]; | ||
| 696 | stat->firewire_bus_voltage = r->operand[29]; | ||
| 697 | stat->ca_mmi = r->operand[30] & 1; | ||
| 698 | stat->ca_pmt_reply = r->operand[31] >> 7 & 1; | ||
| 699 | stat->ca_date_time_request = r->operand[31] >> 6 & 1; | ||
| 700 | stat->ca_application_info = r->operand[31] >> 5 & 1; | ||
| 701 | stat->ca_module_present_status = r->operand[31] >> 4 & 1; | ||
| 702 | stat->ca_dvb_flag = r->operand[31] >> 3 & 1; | ||
| 703 | stat->ca_error_flag = r->operand[31] >> 2 & 1; | ||
| 704 | stat->ca_initialization_status = r->operand[31] >> 1 & 1; | ||
| 705 | |||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
| 710 | char conttone, char nrdiseq, | ||
| 711 | struct dvb_diseqc_master_cmd *diseqcmd) | ||
| 712 | { | ||
| 713 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 714 | struct avc_command_frame *c = (void *)buffer; | ||
| 715 | struct avc_response_frame *r = (void *)buffer; | ||
| 716 | int i, j, k; | ||
| 717 | |||
| 718 | memset(c, 0, sizeof(*c)); | ||
| 719 | |||
| 720 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 721 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 722 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 723 | |||
| 724 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 725 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 726 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 727 | c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; | ||
| 728 | |||
| 729 | c->operand[4] = voltage; | ||
| 730 | c->operand[5] = nrdiseq; | ||
| 731 | |||
| 732 | i = 6; | ||
| 733 | |||
| 734 | for (j = 0; j < nrdiseq; j++) { | ||
| 735 | c->operand[i++] = diseqcmd[j].msg_len; | ||
| 736 | |||
| 737 | for (k = 0; k < diseqcmd[j].msg_len; k++) | ||
| 738 | c->operand[i++] = diseqcmd[j].msg[k]; | ||
| 739 | } | ||
| 740 | |||
| 741 | c->operand[i++] = burst; | ||
| 742 | c->operand[i++] = conttone; | ||
| 743 | |||
| 744 | c->length = ALIGN(3 + i, 4); | ||
| 745 | |||
| 746 | if (avc_write(fdtv, c, r) < 0) | ||
| 747 | return -EIO; | ||
| 748 | |||
| 749 | if (r->response != AVC_RESPONSE_ACCEPTED) { | ||
| 750 | dev_err(fdtv->device, "LNB control failed\n"); | ||
| 751 | return -EINVAL; | ||
| 752 | } | ||
| 753 | |||
| 754 | return 0; | ||
| 755 | } | ||
| 756 | |||
| 757 | int avc_register_remote_control(struct firedtv *fdtv) | ||
| 758 | { | ||
| 759 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 760 | struct avc_command_frame *c = (void *)buffer; | ||
| 761 | |||
| 762 | memset(c, 0, sizeof(*c)); | ||
| 763 | |||
| 764 | c->ctype = AVC_CTYPE_NOTIFY; | ||
| 765 | c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; | ||
| 766 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 767 | |||
| 768 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 769 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 770 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 771 | c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; | ||
| 772 | |||
| 773 | c->length = 8; | ||
| 774 | |||
| 775 | return avc_write(fdtv, c, NULL); | ||
| 776 | } | ||
| 777 | |||
| 778 | void avc_remote_ctrl_work(struct work_struct *work) | ||
| 779 | { | ||
| 780 | struct firedtv *fdtv = | ||
| 781 | container_of(work, struct firedtv, remote_ctrl_work); | ||
| 782 | |||
| 783 | /* Should it be rescheduled in failure cases? */ | ||
| 784 | avc_register_remote_control(fdtv); | ||
| 785 | } | ||
| 786 | |||
| 787 | #if 0 /* FIXME: unused */ | ||
| 788 | int avc_tuner_host2ca(struct firedtv *fdtv) | ||
| 789 | { | ||
| 790 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 791 | struct avc_command_frame *c = (void *)buffer; | ||
| 792 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 793 | |||
| 794 | memset(c, 0, sizeof(*c)); | ||
| 795 | |||
| 796 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 797 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 798 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 799 | |||
| 800 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 801 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 802 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 803 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
| 804 | c->operand[4] = 0; /* slot */ | ||
| 805 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
| 806 | c->operand[6] = 0; /* more/last */ | ||
| 807 | c->operand[7] = 0; /* length */ | ||
| 808 | |||
| 809 | c->length = 12; | ||
| 810 | |||
| 811 | if (avc_write(fdtv, c, r) < 0) | ||
| 812 | return -EIO; | ||
| 813 | |||
| 814 | return 0; | ||
| 815 | } | ||
| 816 | #endif | ||
| 817 | |||
| 818 | static int get_ca_object_pos(struct avc_response_frame *r) | ||
| 819 | { | ||
| 820 | int length = 1; | ||
| 821 | |||
| 822 | /* Check length of length field */ | ||
| 823 | if (r->operand[7] & 0x80) | ||
| 824 | length = (r->operand[7] & 0x7f) + 1; | ||
| 825 | return length + 7; | ||
| 826 | } | ||
| 827 | |||
| 828 | static int get_ca_object_length(struct avc_response_frame *r) | ||
| 829 | { | ||
| 830 | #if 0 /* FIXME: unused */ | ||
| 831 | int size = 0; | ||
| 832 | int i; | ||
| 833 | |||
| 834 | if (r->operand[7] & 0x80) | ||
| 835 | for (i = 0; i < (r->operand[7] & 0x7f); i++) { | ||
| 836 | size <<= 8; | ||
| 837 | size += r->operand[8 + i]; | ||
| 838 | } | ||
| 839 | #endif | ||
| 840 | return r->operand[7]; | ||
| 841 | } | ||
| 842 | |||
| 843 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
| 844 | { | ||
| 845 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 846 | struct avc_command_frame *c = (void *)buffer; | ||
| 847 | struct avc_response_frame *r = (void *)buffer; | ||
| 848 | int pos; | ||
| 849 | |||
| 850 | memset(c, 0, sizeof(*c)); | ||
| 851 | |||
| 852 | c->ctype = AVC_CTYPE_STATUS; | ||
| 853 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 854 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 855 | |||
| 856 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 857 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 858 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 859 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
| 860 | c->operand[4] = 0; /* slot */ | ||
| 861 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
| 862 | |||
| 863 | c->length = 12; | ||
| 864 | |||
| 865 | if (avc_write(fdtv, c, r) < 0) | ||
| 866 | return -EIO; | ||
| 867 | |||
| 868 | /* FIXME: check response code and validate response data */ | ||
| 869 | |||
| 870 | pos = get_ca_object_pos(r); | ||
| 871 | app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff; | ||
| 872 | app_info[1] = (EN50221_TAG_APP_INFO >> 8) & 0xff; | ||
| 873 | app_info[2] = (EN50221_TAG_APP_INFO >> 0) & 0xff; | ||
| 874 | app_info[3] = 6 + r->operand[pos + 4]; | ||
| 875 | app_info[4] = 0x01; | ||
| 876 | memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); | ||
| 877 | *len = app_info[3] + 4; | ||
| 878 | |||
| 879 | return 0; | ||
| 880 | } | ||
| 881 | |||
| 882 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
| 883 | { | ||
| 884 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 885 | struct avc_command_frame *c = (void *)buffer; | ||
| 886 | struct avc_response_frame *r = (void *)buffer; | ||
| 887 | int pos; | ||
| 888 | |||
| 889 | memset(c, 0, sizeof(*c)); | ||
| 890 | |||
| 891 | c->ctype = AVC_CTYPE_STATUS; | ||
| 892 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 893 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 894 | |||
| 895 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 896 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 897 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 898 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
| 899 | c->operand[4] = 0; /* slot */ | ||
| 900 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
| 901 | |||
| 902 | c->length = 12; | ||
| 903 | |||
| 904 | if (avc_write(fdtv, c, r) < 0) | ||
| 905 | return -EIO; | ||
| 906 | |||
| 907 | pos = get_ca_object_pos(r); | ||
| 908 | app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; | ||
| 909 | app_info[1] = (EN50221_TAG_CA_INFO >> 8) & 0xff; | ||
| 910 | app_info[2] = (EN50221_TAG_CA_INFO >> 0) & 0xff; | ||
| 911 | app_info[3] = 2; | ||
| 912 | app_info[4] = r->operand[pos + 0]; | ||
| 913 | app_info[5] = r->operand[pos + 1]; | ||
| 914 | *len = app_info[3] + 4; | ||
| 915 | |||
| 916 | return 0; | ||
| 917 | } | ||
| 918 | |||
| 919 | int avc_ca_reset(struct firedtv *fdtv) | ||
| 920 | { | ||
| 921 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 922 | struct avc_command_frame *c = (void *)buffer; | ||
| 923 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 924 | |||
| 925 | memset(c, 0, sizeof(*c)); | ||
| 926 | |||
| 927 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 928 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 929 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 930 | |||
| 931 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 932 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 933 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 934 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
| 935 | c->operand[4] = 0; /* slot */ | ||
| 936 | c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */ | ||
| 937 | c->operand[6] = 0; /* more/last */ | ||
| 938 | c->operand[7] = 1; /* length */ | ||
| 939 | c->operand[8] = 0; /* force hardware reset */ | ||
| 940 | |||
| 941 | c->length = 12; | ||
| 942 | |||
| 943 | if (avc_write(fdtv, c, r) < 0) | ||
| 944 | return -EIO; | ||
| 945 | |||
| 946 | return 0; | ||
| 947 | } | ||
| 948 | |||
| 949 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | ||
| 950 | { | ||
| 951 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 952 | struct avc_command_frame *c = (void *)buffer; | ||
| 953 | struct avc_response_frame *r = (void *)buffer; | ||
| 954 | int list_management; | ||
| 955 | int program_info_length; | ||
| 956 | int pmt_cmd_id; | ||
| 957 | int read_pos; | ||
| 958 | int write_pos; | ||
| 959 | int es_info_length; | ||
| 960 | int crc32_csum; | ||
| 961 | |||
| 962 | memset(c, 0, sizeof(*c)); | ||
| 963 | |||
| 964 | c->ctype = AVC_CTYPE_CONTROL; | ||
| 965 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 966 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 967 | |||
| 968 | if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) { | ||
| 969 | dev_info(fdtv->device, "forcing list_management to ONLY\n"); | ||
| 970 | msg[0] = EN50221_LIST_MANAGEMENT_ONLY; | ||
| 971 | } | ||
| 972 | /* We take the cmd_id from the programme level only! */ | ||
| 973 | list_management = msg[0]; | ||
| 974 | program_info_length = ((msg[4] & 0x0f) << 8) + msg[5]; | ||
| 975 | if (program_info_length > 0) | ||
| 976 | program_info_length--; /* Remove pmt_cmd_id */ | ||
| 977 | pmt_cmd_id = msg[6]; | ||
| 978 | |||
| 979 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 980 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 981 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 982 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
| 983 | c->operand[4] = 0; /* slot */ | ||
| 984 | c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */ | ||
| 985 | c->operand[6] = 0; /* more/last */ | ||
| 986 | /* c->operand[7] = XXXprogram_info_length + 17; */ /* length */ | ||
| 987 | c->operand[8] = list_management; | ||
| 988 | c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */ | ||
| 989 | |||
| 990 | /* TS program map table */ | ||
| 991 | |||
| 992 | c->operand[10] = 0x02; /* Table id=2 */ | ||
| 993 | c->operand[11] = 0x80; /* Section syntax + length */ | ||
| 994 | /* c->operand[12] = XXXprogram_info_length + 12; */ | ||
| 995 | c->operand[13] = msg[1]; /* Program number */ | ||
| 996 | c->operand[14] = msg[2]; | ||
| 997 | c->operand[15] = 0x01; /* Version number=0 + current/next=1 */ | ||
| 998 | c->operand[16] = 0x00; /* Section number=0 */ | ||
| 999 | c->operand[17] = 0x00; /* Last section number=0 */ | ||
| 1000 | c->operand[18] = 0x1f; /* PCR_PID=1FFF */ | ||
| 1001 | c->operand[19] = 0xff; | ||
| 1002 | c->operand[20] = (program_info_length >> 8); /* Program info length */ | ||
| 1003 | c->operand[21] = (program_info_length & 0xff); | ||
| 1004 | |||
| 1005 | /* CA descriptors at programme level */ | ||
| 1006 | read_pos = 6; | ||
| 1007 | write_pos = 22; | ||
| 1008 | if (program_info_length > 0) { | ||
| 1009 | pmt_cmd_id = msg[read_pos++]; | ||
| 1010 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
| 1011 | dev_err(fdtv->device, | ||
| 1012 | "invalid pmt_cmd_id %d\n", pmt_cmd_id); | ||
| 1013 | |||
| 1014 | memcpy(&c->operand[write_pos], &msg[read_pos], | ||
| 1015 | program_info_length); | ||
| 1016 | read_pos += program_info_length; | ||
| 1017 | write_pos += program_info_length; | ||
| 1018 | } | ||
| 1019 | while (read_pos < length) { | ||
| 1020 | c->operand[write_pos++] = msg[read_pos++]; | ||
| 1021 | c->operand[write_pos++] = msg[read_pos++]; | ||
| 1022 | c->operand[write_pos++] = msg[read_pos++]; | ||
| 1023 | es_info_length = | ||
| 1024 | ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1]; | ||
| 1025 | read_pos += 2; | ||
| 1026 | if (es_info_length > 0) | ||
| 1027 | es_info_length--; /* Remove pmt_cmd_id */ | ||
| 1028 | c->operand[write_pos++] = es_info_length >> 8; | ||
| 1029 | c->operand[write_pos++] = es_info_length & 0xff; | ||
| 1030 | if (es_info_length > 0) { | ||
| 1031 | pmt_cmd_id = msg[read_pos++]; | ||
| 1032 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
| 1033 | dev_err(fdtv->device, "invalid pmt_cmd_id %d " | ||
| 1034 | "at stream level\n", pmt_cmd_id); | ||
| 1035 | |||
| 1036 | memcpy(&c->operand[write_pos], &msg[read_pos], | ||
| 1037 | es_info_length); | ||
| 1038 | read_pos += es_info_length; | ||
| 1039 | write_pos += es_info_length; | ||
| 1040 | } | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | /* CRC */ | ||
| 1044 | c->operand[write_pos++] = 0x00; | ||
| 1045 | c->operand[write_pos++] = 0x00; | ||
| 1046 | c->operand[write_pos++] = 0x00; | ||
| 1047 | c->operand[write_pos++] = 0x00; | ||
| 1048 | |||
| 1049 | c->operand[7] = write_pos - 8; | ||
| 1050 | c->operand[12] = write_pos - 13; | ||
| 1051 | |||
| 1052 | crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1); | ||
| 1053 | c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff; | ||
| 1054 | c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; | ||
| 1055 | c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; | ||
| 1056 | c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; | ||
| 1057 | |||
| 1058 | c->length = ALIGN(3 + write_pos, 4); | ||
| 1059 | |||
| 1060 | if (avc_write(fdtv, c, r) < 0) | ||
| 1061 | return -EIO; | ||
| 1062 | |||
| 1063 | if (r->response != AVC_RESPONSE_ACCEPTED) { | ||
| 1064 | dev_err(fdtv->device, | ||
| 1065 | "CA PMT failed with response 0x%x\n", r->response); | ||
| 1066 | return -EFAULT; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | return 0; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | ||
| 1073 | { | ||
| 1074 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 1075 | struct avc_command_frame *c = (void *)buffer; | ||
| 1076 | struct avc_response_frame *r = (void *)buffer; | ||
| 1077 | |||
| 1078 | memset(c, 0, sizeof(*c)); | ||
| 1079 | |||
| 1080 | c->ctype = AVC_CTYPE_STATUS; | ||
| 1081 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 1082 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 1083 | |||
| 1084 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 1085 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 1086 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 1087 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
| 1088 | c->operand[4] = 0; /* slot */ | ||
| 1089 | c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ | ||
| 1090 | c->operand[6] = 0; /* more/last */ | ||
| 1091 | c->operand[7] = 0; /* length */ | ||
| 1092 | |||
| 1093 | c->length = 12; | ||
| 1094 | |||
| 1095 | if (avc_write(fdtv, c, r) < 0) | ||
| 1096 | return -EIO; | ||
| 1097 | |||
| 1098 | /* FIXME: check response code and validate response data */ | ||
| 1099 | |||
| 1100 | *interval = r->operand[get_ca_object_pos(r)]; | ||
| 1101 | |||
| 1102 | return 0; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | int avc_ca_enter_menu(struct firedtv *fdtv) | ||
| 1106 | { | ||
| 1107 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 1108 | struct avc_command_frame *c = (void *)buffer; | ||
| 1109 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
| 1110 | |||
| 1111 | memset(c, 0, sizeof(*c)); | ||
| 1112 | |||
| 1113 | c->ctype = AVC_CTYPE_STATUS; | ||
| 1114 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 1115 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 1116 | |||
| 1117 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 1118 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 1119 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 1120 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
| 1121 | c->operand[4] = 0; /* slot */ | ||
| 1122 | c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; | ||
| 1123 | c->operand[6] = 0; /* more/last */ | ||
| 1124 | c->operand[7] = 0; /* length */ | ||
| 1125 | |||
| 1126 | c->length = 12; | ||
| 1127 | |||
| 1128 | if (avc_write(fdtv, c, r) < 0) | ||
| 1129 | return -EIO; | ||
| 1130 | |||
| 1131 | return 0; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | ||
| 1135 | { | ||
| 1136 | char buffer[sizeof(struct avc_command_frame)]; | ||
| 1137 | struct avc_command_frame *c = (void *)buffer; | ||
| 1138 | struct avc_response_frame *r = (void *)buffer; | ||
| 1139 | |||
| 1140 | memset(c, 0, sizeof(*c)); | ||
| 1141 | |||
| 1142 | c->ctype = AVC_CTYPE_STATUS; | ||
| 1143 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
| 1144 | c->opcode = AVC_OPCODE_VENDOR; | ||
| 1145 | |||
| 1146 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
| 1147 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
| 1148 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
| 1149 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
| 1150 | c->operand[4] = 0; /* slot */ | ||
| 1151 | c->operand[5] = SFE_VENDOR_TAG_CA_MMI; | ||
| 1152 | c->operand[6] = 0; /* more/last */ | ||
| 1153 | c->operand[7] = 0; /* length */ | ||
| 1154 | |||
| 1155 | c->length = 12; | ||
| 1156 | |||
| 1157 | if (avc_write(fdtv, c, r) < 0) | ||
| 1158 | return -EIO; | ||
| 1159 | |||
| 1160 | /* FIXME: check response code and validate response data */ | ||
| 1161 | |||
| 1162 | *len = get_ca_object_length(r); | ||
| 1163 | memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); | ||
| 1164 | |||
| 1165 | return 0; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL | ||
| 1169 | |||
| 1170 | static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len) | ||
| 1171 | { | ||
| 1172 | int ret; | ||
| 1173 | |||
| 1174 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
| 1175 | return -EINTR; | ||
| 1176 | |||
| 1177 | ret = fdtv->backend->read(fdtv, addr, buf, len); | ||
| 1178 | if (ret < 0) | ||
| 1179 | dev_err(fdtv->device, "CMP: read I/O error\n"); | ||
| 1180 | |||
| 1181 | mutex_unlock(&fdtv->avc_mutex); | ||
| 1182 | return ret; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg) | ||
| 1186 | { | ||
| 1187 | int ret; | ||
| 1188 | |||
| 1189 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
| 1190 | return -EINTR; | ||
| 1191 | |||
| 1192 | ret = fdtv->backend->lock(fdtv, addr, data, arg); | ||
| 1193 | if (ret < 0) | ||
| 1194 | dev_err(fdtv->device, "CMP: lock I/O error\n"); | ||
| 1195 | |||
| 1196 | mutex_unlock(&fdtv->avc_mutex); | ||
| 1197 | return ret; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift) | ||
| 1201 | { | ||
| 1202 | return (be32_to_cpu(opcr) >> shift) & mask; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift) | ||
| 1206 | { | ||
| 1207 | *opcr &= ~cpu_to_be32(mask << shift); | ||
| 1208 | *opcr |= cpu_to_be32((value & mask) << shift); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | #define get_opcr_online(v) get_opcr((v), 0x1, 31) | ||
| 1212 | #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24) | ||
| 1213 | #define get_opcr_channel(v) get_opcr((v), 0x3f, 16) | ||
| 1214 | |||
| 1215 | #define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24) | ||
| 1216 | #define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16) | ||
| 1217 | #define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14) | ||
| 1218 | #define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10) | ||
| 1219 | |||
| 1220 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
| 1221 | { | ||
| 1222 | __be32 old_opcr, opcr; | ||
| 1223 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
| 1224 | int attempts = 0; | ||
| 1225 | int ret; | ||
| 1226 | |||
| 1227 | ret = cmp_read(fdtv, &opcr, opcr_address, 4); | ||
| 1228 | if (ret < 0) | ||
| 1229 | return ret; | ||
| 1230 | |||
| 1231 | repeat: | ||
| 1232 | if (!get_opcr_online(opcr)) { | ||
| 1233 | dev_err(fdtv->device, "CMP: output offline\n"); | ||
| 1234 | return -EBUSY; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | old_opcr = opcr; | ||
| 1238 | |||
| 1239 | if (get_opcr_p2p_connections(opcr)) { | ||
| 1240 | if (get_opcr_channel(opcr) != channel) { | ||
| 1241 | dev_err(fdtv->device, "CMP: cannot change channel\n"); | ||
| 1242 | return -EBUSY; | ||
| 1243 | } | ||
| 1244 | dev_info(fdtv->device, "CMP: overlaying connection\n"); | ||
| 1245 | |||
| 1246 | /* We don't allocate isochronous resources. */ | ||
| 1247 | } else { | ||
| 1248 | set_opcr_channel(&opcr, channel); | ||
| 1249 | set_opcr_data_rate(&opcr, 2); /* S400 */ | ||
| 1250 | |||
| 1251 | /* FIXME: this is for the worst case - optimize */ | ||
| 1252 | set_opcr_overhead_id(&opcr, 0); | ||
| 1253 | |||
| 1254 | /* | ||
| 1255 | * FIXME: allocate isochronous channel and bandwidth at IRM | ||
| 1256 | * fdtv->backend->alloc_resources(fdtv, channels_mask, bw); | ||
| 1257 | */ | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1); | ||
| 1261 | |||
| 1262 | ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr); | ||
| 1263 | if (ret < 0) | ||
| 1264 | return ret; | ||
| 1265 | |||
| 1266 | if (old_opcr != opcr) { | ||
| 1267 | /* | ||
| 1268 | * FIXME: if old_opcr.P2P_Connections > 0, | ||
| 1269 | * deallocate isochronous channel and bandwidth at IRM | ||
| 1270 | * if (...) | ||
| 1271 | * fdtv->backend->dealloc_resources(fdtv, channel, bw); | ||
| 1272 | */ | ||
| 1273 | |||
| 1274 | if (++attempts < 6) /* arbitrary limit */ | ||
| 1275 | goto repeat; | ||
| 1276 | return -EBUSY; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | return 0; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
| 1283 | { | ||
| 1284 | __be32 old_opcr, opcr; | ||
| 1285 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
| 1286 | int attempts = 0; | ||
| 1287 | |||
| 1288 | if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0) | ||
| 1289 | return; | ||
| 1290 | |||
| 1291 | repeat: | ||
| 1292 | if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) || | ||
| 1293 | get_opcr_channel(opcr) != channel) { | ||
| 1294 | dev_err(fdtv->device, "CMP: no connection to break\n"); | ||
| 1295 | return; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | old_opcr = opcr; | ||
| 1299 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1); | ||
| 1300 | |||
| 1301 | if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0) | ||
| 1302 | return; | ||
| 1303 | |||
| 1304 | if (old_opcr != opcr) { | ||
| 1305 | /* | ||
| 1306 | * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last | ||
| 1307 | * owner, deallocate isochronous channel and bandwidth at IRM | ||
| 1308 | * if (...) | ||
| 1309 | * fdtv->backend->dealloc_resources(fdtv, channel, bw); | ||
| 1310 | */ | ||
| 1311 | |||
| 1312 | if (++attempts < 6) /* arbitrary limit */ | ||
| 1313 | goto repeat; | ||
| 1314 | } | ||
| 1315 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c new file mode 100644 index 00000000000..eeb80d0ea3f --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-ci.c | |||
| @@ -0,0 +1,260 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation; either version 2 of | ||
| 10 | * the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/dvb/ca.h> | ||
| 15 | #include <linux/fs.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | #include <dvbdev.h> | ||
| 19 | |||
| 20 | #include "firedtv.h" | ||
| 21 | |||
| 22 | #define EN50221_TAG_APP_INFO_ENQUIRY 0x9f8020 | ||
| 23 | #define EN50221_TAG_CA_INFO_ENQUIRY 0x9f8030 | ||
| 24 | #define EN50221_TAG_CA_PMT 0x9f8032 | ||
| 25 | #define EN50221_TAG_ENTER_MENU 0x9f8022 | ||
| 26 | |||
| 27 | static int fdtv_ca_ready(struct firedtv_tuner_status *stat) | ||
| 28 | { | ||
| 29 | return stat->ca_initialization_status == 1 && | ||
| 30 | stat->ca_error_flag == 0 && | ||
| 31 | stat->ca_dvb_flag == 1 && | ||
| 32 | stat->ca_module_present_status == 1; | ||
| 33 | } | ||
| 34 | |||
| 35 | static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat) | ||
| 36 | { | ||
| 37 | int flags = 0; | ||
| 38 | |||
| 39 | if (stat->ca_module_present_status == 1) | ||
| 40 | flags |= CA_CI_MODULE_PRESENT; | ||
| 41 | if (stat->ca_initialization_status == 1 && | ||
| 42 | stat->ca_error_flag == 0 && | ||
| 43 | stat->ca_dvb_flag == 1) | ||
| 44 | flags |= CA_CI_MODULE_READY; | ||
| 45 | return flags; | ||
| 46 | } | ||
| 47 | |||
| 48 | static int fdtv_ca_reset(struct firedtv *fdtv) | ||
| 49 | { | ||
| 50 | return avc_ca_reset(fdtv) ? -EFAULT : 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int fdtv_ca_get_caps(void *arg) | ||
| 54 | { | ||
| 55 | struct ca_caps *cap = arg; | ||
| 56 | |||
| 57 | cap->slot_num = 1; | ||
| 58 | cap->slot_type = CA_CI; | ||
| 59 | cap->descr_num = 1; | ||
| 60 | cap->descr_type = CA_ECD; | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg) | ||
| 65 | { | ||
| 66 | struct firedtv_tuner_status stat; | ||
| 67 | struct ca_slot_info *slot = arg; | ||
| 68 | |||
| 69 | if (avc_tuner_status(fdtv, &stat)) | ||
| 70 | return -EFAULT; | ||
| 71 | |||
| 72 | if (slot->num != 0) | ||
| 73 | return -EFAULT; | ||
| 74 | |||
| 75 | slot->type = CA_CI; | ||
| 76 | slot->flags = fdtv_get_ca_flags(&stat); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg) | ||
| 81 | { | ||
| 82 | struct ca_msg *reply = arg; | ||
| 83 | |||
| 84 | return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int fdtv_ca_info(struct firedtv *fdtv, void *arg) | ||
| 88 | { | ||
| 89 | struct ca_msg *reply = arg; | ||
| 90 | |||
| 91 | return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg) | ||
| 95 | { | ||
| 96 | struct ca_msg *reply = arg; | ||
| 97 | |||
| 98 | return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg) | ||
| 102 | { | ||
| 103 | struct firedtv_tuner_status stat; | ||
| 104 | int err; | ||
| 105 | |||
| 106 | switch (fdtv->ca_last_command) { | ||
| 107 | case EN50221_TAG_APP_INFO_ENQUIRY: | ||
| 108 | err = fdtv_ca_app_info(fdtv, arg); | ||
| 109 | break; | ||
| 110 | case EN50221_TAG_CA_INFO_ENQUIRY: | ||
| 111 | err = fdtv_ca_info(fdtv, arg); | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | if (avc_tuner_status(fdtv, &stat)) | ||
| 115 | err = -EFAULT; | ||
| 116 | else if (stat.ca_mmi == 1) | ||
| 117 | err = fdtv_ca_get_mmi(fdtv, arg); | ||
| 118 | else { | ||
| 119 | dev_info(fdtv->device, "unhandled CA message 0x%08x\n", | ||
| 120 | fdtv->ca_last_command); | ||
| 121 | err = -EFAULT; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | fdtv->ca_last_command = 0; | ||
| 125 | return err; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) | ||
| 129 | { | ||
| 130 | struct ca_msg *msg = arg; | ||
| 131 | int data_pos; | ||
| 132 | int data_length; | ||
| 133 | int i; | ||
| 134 | |||
| 135 | data_pos = 4; | ||
| 136 | if (msg->msg[3] & 0x80) { | ||
| 137 | data_length = 0; | ||
| 138 | for (i = 0; i < (msg->msg[3] & 0x7f); i++) | ||
| 139 | data_length = (data_length << 8) + msg->msg[data_pos++]; | ||
| 140 | } else { | ||
| 141 | data_length = msg->msg[3]; | ||
| 142 | } | ||
| 143 | |||
| 144 | return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg) | ||
| 148 | { | ||
| 149 | struct ca_msg *msg = arg; | ||
| 150 | int err; | ||
| 151 | |||
| 152 | /* Do we need a semaphore for this? */ | ||
| 153 | fdtv->ca_last_command = | ||
| 154 | (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2]; | ||
| 155 | switch (fdtv->ca_last_command) { | ||
| 156 | case EN50221_TAG_CA_PMT: | ||
| 157 | err = fdtv_ca_pmt(fdtv, arg); | ||
| 158 | break; | ||
| 159 | case EN50221_TAG_APP_INFO_ENQUIRY: | ||
| 160 | /* handled in ca_get_msg */ | ||
| 161 | err = 0; | ||
| 162 | break; | ||
| 163 | case EN50221_TAG_CA_INFO_ENQUIRY: | ||
| 164 | /* handled in ca_get_msg */ | ||
| 165 | err = 0; | ||
| 166 | break; | ||
| 167 | case EN50221_TAG_ENTER_MENU: | ||
| 168 | err = avc_ca_enter_menu(fdtv); | ||
| 169 | break; | ||
| 170 | default: | ||
| 171 | dev_err(fdtv->device, "unhandled CA message 0x%08x\n", | ||
| 172 | fdtv->ca_last_command); | ||
| 173 | err = -EFAULT; | ||
| 174 | } | ||
| 175 | return err; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int fdtv_ca_ioctl(struct inode *inode, struct file *file, | ||
| 179 | unsigned int cmd, void *arg) | ||
| 180 | { | ||
| 181 | struct dvb_device *dvbdev = file->private_data; | ||
| 182 | struct firedtv *fdtv = dvbdev->priv; | ||
| 183 | struct firedtv_tuner_status stat; | ||
| 184 | int err; | ||
| 185 | |||
| 186 | switch (cmd) { | ||
| 187 | case CA_RESET: | ||
| 188 | err = fdtv_ca_reset(fdtv); | ||
| 189 | break; | ||
| 190 | case CA_GET_CAP: | ||
| 191 | err = fdtv_ca_get_caps(arg); | ||
| 192 | break; | ||
| 193 | case CA_GET_SLOT_INFO: | ||
| 194 | err = fdtv_ca_get_slot_info(fdtv, arg); | ||
| 195 | break; | ||
| 196 | case CA_GET_MSG: | ||
| 197 | err = fdtv_ca_get_msg(fdtv, arg); | ||
| 198 | break; | ||
| 199 | case CA_SEND_MSG: | ||
| 200 | err = fdtv_ca_send_msg(fdtv, arg); | ||
| 201 | break; | ||
| 202 | default: | ||
| 203 | dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd); | ||
| 204 | err = -EOPNOTSUPP; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* FIXME Is this necessary? */ | ||
| 208 | avc_tuner_status(fdtv, &stat); | ||
| 209 | |||
| 210 | return err; | ||
| 211 | } | ||
| 212 | |||
| 213 | static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait) | ||
| 214 | { | ||
| 215 | return POLLIN; | ||
| 216 | } | ||
| 217 | |||
| 218 | static struct file_operations fdtv_ca_fops = { | ||
| 219 | .owner = THIS_MODULE, | ||
| 220 | .ioctl = dvb_generic_ioctl, | ||
| 221 | .open = dvb_generic_open, | ||
| 222 | .release = dvb_generic_release, | ||
| 223 | .poll = fdtv_ca_io_poll, | ||
| 224 | }; | ||
| 225 | |||
| 226 | static struct dvb_device fdtv_ca = { | ||
| 227 | .users = 1, | ||
| 228 | .readers = 1, | ||
| 229 | .writers = 1, | ||
| 230 | .fops = &fdtv_ca_fops, | ||
| 231 | .kernel_ioctl = fdtv_ca_ioctl, | ||
| 232 | }; | ||
| 233 | |||
| 234 | int fdtv_ca_register(struct firedtv *fdtv) | ||
| 235 | { | ||
| 236 | struct firedtv_tuner_status stat; | ||
| 237 | int err; | ||
| 238 | |||
| 239 | if (avc_tuner_status(fdtv, &stat)) | ||
| 240 | return -EINVAL; | ||
| 241 | |||
| 242 | if (!fdtv_ca_ready(&stat)) | ||
| 243 | return -EFAULT; | ||
| 244 | |||
| 245 | err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, | ||
| 246 | &fdtv_ca, fdtv, DVB_DEVICE_CA); | ||
| 247 | |||
| 248 | if (stat.ca_application_info == 0) | ||
| 249 | dev_err(fdtv->device, "CaApplicationInfo is not set\n"); | ||
| 250 | if (stat.ca_date_time_request == 1) | ||
| 251 | avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval); | ||
| 252 | |||
| 253 | return err; | ||
| 254 | } | ||
| 255 | |||
| 256 | void fdtv_ca_release(struct firedtv *fdtv) | ||
| 257 | { | ||
| 258 | if (fdtv->cadev) | ||
| 259 | dvb_unregister_device(fdtv->cadev); | ||
| 260 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c new file mode 100644 index 00000000000..9d308dd32a5 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-dvb.c | |||
| @@ -0,0 +1,364 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation; either version 2 of | ||
| 10 | * the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/bitops.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/mod_devicetable.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | #include <linux/wait.h> | ||
| 24 | #include <linux/workqueue.h> | ||
| 25 | |||
| 26 | #include <dmxdev.h> | ||
| 27 | #include <dvb_demux.h> | ||
| 28 | #include <dvbdev.h> | ||
| 29 | #include <dvb_frontend.h> | ||
| 30 | |||
| 31 | #include "firedtv.h" | ||
| 32 | |||
| 33 | static int alloc_channel(struct firedtv *fdtv) | ||
| 34 | { | ||
| 35 | int i; | ||
| 36 | |||
| 37 | for (i = 0; i < 16; i++) | ||
| 38 | if (!__test_and_set_bit(i, &fdtv->channel_active)) | ||
| 39 | break; | ||
| 40 | return i; | ||
| 41 | } | ||
| 42 | |||
| 43 | static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[]) | ||
| 44 | { | ||
| 45 | int i, n; | ||
| 46 | |||
| 47 | for (i = 0, n = 0; i < 16; i++) | ||
| 48 | if (test_bit(i, &fdtv->channel_active)) | ||
| 49 | pid[n++] = fdtv->channel_pid[i]; | ||
| 50 | *pidc = n; | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline void dealloc_channel(struct firedtv *fdtv, int i) | ||
| 54 | { | ||
| 55 | __clear_bit(i, &fdtv->channel_active); | ||
| 56 | } | ||
| 57 | |||
| 58 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 59 | { | ||
| 60 | struct firedtv *fdtv = dvbdmxfeed->demux->priv; | ||
| 61 | int pidc, c, ret; | ||
| 62 | u16 pids[16]; | ||
| 63 | |||
| 64 | switch (dvbdmxfeed->type) { | ||
| 65 | case DMX_TYPE_TS: | ||
| 66 | case DMX_TYPE_SEC: | ||
| 67 | break; | ||
| 68 | default: | ||
| 69 | dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n", | ||
| 70 | dvbdmxfeed->type); | ||
| 71 | return -EINVAL; | ||
| 72 | } | ||
| 73 | |||
| 74 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
| 75 | return -EINTR; | ||
| 76 | |||
| 77 | if (dvbdmxfeed->type == DMX_TYPE_TS) { | ||
| 78 | switch (dvbdmxfeed->pes_type) { | ||
| 79 | case DMX_TS_PES_VIDEO: | ||
| 80 | case DMX_TS_PES_AUDIO: | ||
| 81 | case DMX_TS_PES_TELETEXT: | ||
| 82 | case DMX_TS_PES_PCR: | ||
| 83 | case DMX_TS_PES_OTHER: | ||
| 84 | c = alloc_channel(fdtv); | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | dev_err(fdtv->device, | ||
| 88 | "can't start dmx feed: invalid pes type %u\n", | ||
| 89 | dvbdmxfeed->pes_type); | ||
| 90 | ret = -EINVAL; | ||
| 91 | goto out; | ||
| 92 | } | ||
| 93 | } else { | ||
| 94 | c = alloc_channel(fdtv); | ||
| 95 | } | ||
| 96 | |||
| 97 | if (c > 15) { | ||
| 98 | dev_err(fdtv->device, "can't start dmx feed: busy\n"); | ||
| 99 | ret = -EBUSY; | ||
| 100 | goto out; | ||
| 101 | } | ||
| 102 | |||
| 103 | dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c; | ||
| 104 | fdtv->channel_pid[c] = dvbdmxfeed->pid; | ||
| 105 | collect_channels(fdtv, &pidc, pids); | ||
| 106 | |||
| 107 | if (dvbdmxfeed->pid == 8192) { | ||
| 108 | ret = avc_tuner_get_ts(fdtv); | ||
| 109 | if (ret) { | ||
| 110 | dealloc_channel(fdtv, c); | ||
| 111 | dev_err(fdtv->device, "can't get TS\n"); | ||
| 112 | goto out; | ||
| 113 | } | ||
| 114 | } else { | ||
| 115 | ret = avc_tuner_set_pids(fdtv, pidc, pids); | ||
| 116 | if (ret) { | ||
| 117 | dealloc_channel(fdtv, c); | ||
| 118 | dev_err(fdtv->device, "can't set PIDs\n"); | ||
| 119 | goto out; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | out: | ||
| 123 | mutex_unlock(&fdtv->demux_mutex); | ||
| 124 | |||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | |||
| 128 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 129 | { | ||
| 130 | struct dvb_demux *demux = dvbdmxfeed->demux; | ||
| 131 | struct firedtv *fdtv = demux->priv; | ||
| 132 | int pidc, c, ret; | ||
| 133 | u16 pids[16]; | ||
| 134 | |||
| 135 | if (dvbdmxfeed->type == DMX_TYPE_TS && | ||
| 136 | !((dvbdmxfeed->ts_type & TS_PACKET) && | ||
| 137 | (demux->dmx.frontend->source != DMX_MEMORY_FE))) { | ||
| 138 | |||
| 139 | if (dvbdmxfeed->ts_type & TS_DECODER) { | ||
| 140 | if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER || | ||
| 141 | !demux->pesfilter[dvbdmxfeed->pes_type]) | ||
| 142 | return -EINVAL; | ||
| 143 | |||
| 144 | demux->pids[dvbdmxfeed->pes_type] |= 0x8000; | ||
| 145 | demux->pesfilter[dvbdmxfeed->pes_type] = NULL; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (!(dvbdmxfeed->ts_type & TS_DECODER && | ||
| 149 | dvbdmxfeed->pes_type < DMX_TS_PES_OTHER)) | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
| 154 | return -EINTR; | ||
| 155 | |||
| 156 | c = (unsigned long)dvbdmxfeed->priv; | ||
| 157 | dealloc_channel(fdtv, c); | ||
| 158 | collect_channels(fdtv, &pidc, pids); | ||
| 159 | |||
| 160 | ret = avc_tuner_set_pids(fdtv, pidc, pids); | ||
| 161 | |||
| 162 | mutex_unlock(&fdtv->demux_mutex); | ||
| 163 | |||
| 164 | return ret; | ||
| 165 | } | ||
| 166 | |||
| 167 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 168 | |||
| 169 | int fdtv_dvb_register(struct firedtv *fdtv) | ||
| 170 | { | ||
| 171 | int err; | ||
| 172 | |||
| 173 | err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type], | ||
| 174 | THIS_MODULE, fdtv->device, adapter_nr); | ||
| 175 | if (err < 0) | ||
| 176 | goto fail_log; | ||
| 177 | |||
| 178 | /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/ | ||
| 179 | fdtv->demux.dmx.capabilities = 0; | ||
| 180 | |||
| 181 | fdtv->demux.priv = fdtv; | ||
| 182 | fdtv->demux.filternum = 16; | ||
| 183 | fdtv->demux.feednum = 16; | ||
| 184 | fdtv->demux.start_feed = fdtv_start_feed; | ||
| 185 | fdtv->demux.stop_feed = fdtv_stop_feed; | ||
| 186 | fdtv->demux.write_to_decoder = NULL; | ||
| 187 | |||
| 188 | err = dvb_dmx_init(&fdtv->demux); | ||
| 189 | if (err) | ||
| 190 | goto fail_unreg_adapter; | ||
| 191 | |||
| 192 | fdtv->dmxdev.filternum = 16; | ||
| 193 | fdtv->dmxdev.demux = &fdtv->demux.dmx; | ||
| 194 | fdtv->dmxdev.capabilities = 0; | ||
| 195 | |||
| 196 | err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter); | ||
| 197 | if (err) | ||
| 198 | goto fail_dmx_release; | ||
| 199 | |||
| 200 | fdtv->frontend.source = DMX_FRONTEND_0; | ||
| 201 | |||
| 202 | err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
| 203 | if (err) | ||
| 204 | goto fail_dmxdev_release; | ||
| 205 | |||
| 206 | err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx, | ||
| 207 | &fdtv->frontend); | ||
| 208 | if (err) | ||
| 209 | goto fail_rem_frontend; | ||
| 210 | |||
| 211 | dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx); | ||
| 212 | |||
| 213 | fdtv_frontend_init(fdtv); | ||
| 214 | err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe); | ||
| 215 | if (err) | ||
| 216 | goto fail_net_release; | ||
| 217 | |||
| 218 | err = fdtv_ca_register(fdtv); | ||
| 219 | if (err) | ||
| 220 | dev_info(fdtv->device, | ||
| 221 | "Conditional Access Module not enabled\n"); | ||
| 222 | return 0; | ||
| 223 | |||
| 224 | fail_net_release: | ||
| 225 | dvb_net_release(&fdtv->dvbnet); | ||
| 226 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
| 227 | fail_rem_frontend: | ||
| 228 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
| 229 | fail_dmxdev_release: | ||
| 230 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
| 231 | fail_dmx_release: | ||
| 232 | dvb_dmx_release(&fdtv->demux); | ||
| 233 | fail_unreg_adapter: | ||
| 234 | dvb_unregister_adapter(&fdtv->adapter); | ||
| 235 | fail_log: | ||
| 236 | dev_err(fdtv->device, "DVB initialization failed\n"); | ||
| 237 | return err; | ||
| 238 | } | ||
| 239 | |||
| 240 | void fdtv_dvb_unregister(struct firedtv *fdtv) | ||
| 241 | { | ||
| 242 | fdtv_ca_release(fdtv); | ||
| 243 | dvb_unregister_frontend(&fdtv->fe); | ||
| 244 | dvb_net_release(&fdtv->dvbnet); | ||
| 245 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
| 246 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
| 247 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
| 248 | dvb_dmx_release(&fdtv->demux); | ||
| 249 | dvb_unregister_adapter(&fdtv->adapter); | ||
| 250 | } | ||
| 251 | |||
| 252 | const char *fdtv_model_names[] = { | ||
| 253 | [FIREDTV_UNKNOWN] = "unknown type", | ||
| 254 | [FIREDTV_DVB_S] = "FireDTV S/CI", | ||
| 255 | [FIREDTV_DVB_C] = "FireDTV C/CI", | ||
| 256 | [FIREDTV_DVB_T] = "FireDTV T/CI", | ||
| 257 | [FIREDTV_DVB_S2] = "FireDTV S2 ", | ||
| 258 | }; | ||
| 259 | |||
| 260 | struct firedtv *fdtv_alloc(struct device *dev, | ||
| 261 | const struct firedtv_backend *backend, | ||
| 262 | const char *name, size_t name_len) | ||
| 263 | { | ||
| 264 | struct firedtv *fdtv; | ||
| 265 | int i; | ||
| 266 | |||
| 267 | fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); | ||
| 268 | if (!fdtv) | ||
| 269 | return NULL; | ||
| 270 | |||
| 271 | dev->driver_data = fdtv; | ||
| 272 | fdtv->device = dev; | ||
| 273 | fdtv->isochannel = -1; | ||
| 274 | fdtv->voltage = 0xff; | ||
| 275 | fdtv->tone = 0xff; | ||
| 276 | fdtv->backend = backend; | ||
| 277 | |||
| 278 | mutex_init(&fdtv->avc_mutex); | ||
| 279 | init_waitqueue_head(&fdtv->avc_wait); | ||
| 280 | fdtv->avc_reply_received = true; | ||
| 281 | mutex_init(&fdtv->demux_mutex); | ||
| 282 | INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); | ||
| 283 | |||
| 284 | for (i = ARRAY_SIZE(fdtv_model_names); --i; ) | ||
| 285 | if (strlen(fdtv_model_names[i]) <= name_len && | ||
| 286 | strncmp(name, fdtv_model_names[i], name_len) == 0) | ||
| 287 | break; | ||
| 288 | fdtv->type = i; | ||
| 289 | |||
| 290 | return fdtv; | ||
| 291 | } | ||
| 292 | |||
| 293 | #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \ | ||
| 294 | IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION) | ||
| 295 | |||
| 296 | #define DIGITAL_EVERYWHERE_OUI 0x001287 | ||
| 297 | #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d | ||
| 298 | #define AVC_SW_VERSION_ENTRY 0x010001 | ||
| 299 | |||
| 300 | static struct ieee1394_device_id fdtv_id_table[] = { | ||
| 301 | { | ||
| 302 | /* FloppyDTV S/CI and FloppyDTV S2 */ | ||
| 303 | .match_flags = MATCH_FLAGS, | ||
| 304 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 305 | .model_id = 0x000024, | ||
| 306 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 307 | .version = AVC_SW_VERSION_ENTRY, | ||
| 308 | }, { | ||
| 309 | /* FloppyDTV T/CI */ | ||
| 310 | .match_flags = MATCH_FLAGS, | ||
| 311 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 312 | .model_id = 0x000025, | ||
| 313 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 314 | .version = AVC_SW_VERSION_ENTRY, | ||
| 315 | }, { | ||
| 316 | /* FloppyDTV C/CI */ | ||
| 317 | .match_flags = MATCH_FLAGS, | ||
| 318 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 319 | .model_id = 0x000026, | ||
| 320 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 321 | .version = AVC_SW_VERSION_ENTRY, | ||
| 322 | }, { | ||
| 323 | /* FireDTV S/CI and FloppyDTV S2 */ | ||
| 324 | .match_flags = MATCH_FLAGS, | ||
| 325 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 326 | .model_id = 0x000034, | ||
| 327 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 328 | .version = AVC_SW_VERSION_ENTRY, | ||
| 329 | }, { | ||
| 330 | /* FireDTV T/CI */ | ||
| 331 | .match_flags = MATCH_FLAGS, | ||
| 332 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 333 | .model_id = 0x000035, | ||
| 334 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 335 | .version = AVC_SW_VERSION_ENTRY, | ||
| 336 | }, { | ||
| 337 | /* FireDTV C/CI */ | ||
| 338 | .match_flags = MATCH_FLAGS, | ||
| 339 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
| 340 | .model_id = 0x000036, | ||
| 341 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
| 342 | .version = AVC_SW_VERSION_ENTRY, | ||
| 343 | }, {} | ||
| 344 | }; | ||
| 345 | MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); | ||
| 346 | |||
| 347 | static int __init fdtv_init(void) | ||
| 348 | { | ||
| 349 | return fdtv_1394_init(fdtv_id_table); | ||
| 350 | } | ||
| 351 | |||
| 352 | static void __exit fdtv_exit(void) | ||
| 353 | { | ||
| 354 | fdtv_1394_exit(); | ||
| 355 | } | ||
| 356 | |||
| 357 | module_init(fdtv_init); | ||
| 358 | module_exit(fdtv_exit); | ||
| 359 | |||
| 360 | MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>"); | ||
| 361 | MODULE_AUTHOR("Ben Backx <ben@bbackx.com>"); | ||
| 362 | MODULE_DESCRIPTION("FireDTV DVB Driver"); | ||
| 363 | MODULE_LICENSE("GPL"); | ||
| 364 | MODULE_SUPPORTED_DEVICE("FireDTV DVB"); | ||
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c new file mode 100644 index 00000000000..7ba43630a25 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-fe.c | |||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation; either version 2 of | ||
| 10 | * the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | #include <linux/types.h> | ||
| 18 | |||
| 19 | #include <dvb_frontend.h> | ||
| 20 | |||
| 21 | #include "firedtv.h" | ||
| 22 | |||
| 23 | static int fdtv_dvb_init(struct dvb_frontend *fe) | ||
| 24 | { | ||
| 25 | struct firedtv *fdtv = fe->sec_priv; | ||
| 26 | int err; | ||
| 27 | |||
| 28 | /* FIXME - allocate free channel at IRM */ | ||
| 29 | fdtv->isochannel = fdtv->adapter.num; | ||
| 30 | |||
| 31 | err = cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
| 32 | fdtv->isochannel); | ||
| 33 | if (err) { | ||
| 34 | dev_err(fdtv->device, | ||
| 35 | "could not establish point to point connection\n"); | ||
| 36 | return err; | ||
| 37 | } | ||
| 38 | |||
| 39 | return fdtv->backend->start_iso(fdtv); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int fdtv_sleep(struct dvb_frontend *fe) | ||
| 43 | { | ||
| 44 | struct firedtv *fdtv = fe->sec_priv; | ||
| 45 | |||
| 46 | fdtv->backend->stop_iso(fdtv); | ||
| 47 | cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel); | ||
| 48 | fdtv->isochannel = -1; | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | #define LNBCONTROL_DONTCARE 0xff | ||
| 53 | |||
| 54 | static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
| 55 | struct dvb_diseqc_master_cmd *cmd) | ||
| 56 | { | ||
| 57 | struct firedtv *fdtv = fe->sec_priv; | ||
| 58 | |||
| 59 | return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, | ||
| 60 | LNBCONTROL_DONTCARE, 1, cmd); | ||
| 61 | } | ||
| 62 | |||
| 63 | static int fdtv_diseqc_send_burst(struct dvb_frontend *fe, | ||
| 64 | fe_sec_mini_cmd_t minicmd) | ||
| 65 | { | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
| 70 | { | ||
| 71 | struct firedtv *fdtv = fe->sec_priv; | ||
| 72 | |||
| 73 | fdtv->tone = tone; | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int fdtv_set_voltage(struct dvb_frontend *fe, | ||
| 78 | fe_sec_voltage_t voltage) | ||
| 79 | { | ||
| 80 | struct firedtv *fdtv = fe->sec_priv; | ||
| 81 | |||
| 82 | fdtv->voltage = voltage; | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 87 | { | ||
| 88 | struct firedtv *fdtv = fe->sec_priv; | ||
| 89 | struct firedtv_tuner_status stat; | ||
| 90 | |||
| 91 | if (avc_tuner_status(fdtv, &stat)) | ||
| 92 | return -EINVAL; | ||
| 93 | |||
| 94 | if (stat.no_rf) | ||
| 95 | *status = 0; | ||
| 96 | else | ||
| 97 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
| 98 | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 103 | { | ||
| 104 | struct firedtv *fdtv = fe->sec_priv; | ||
| 105 | struct firedtv_tuner_status stat; | ||
| 106 | |||
| 107 | if (avc_tuner_status(fdtv, &stat)) | ||
| 108 | return -EINVAL; | ||
| 109 | |||
| 110 | *ber = stat.ber; | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 115 | { | ||
| 116 | struct firedtv *fdtv = fe->sec_priv; | ||
| 117 | struct firedtv_tuner_status stat; | ||
| 118 | |||
| 119 | if (avc_tuner_status(fdtv, &stat)) | ||
| 120 | return -EINVAL; | ||
| 121 | |||
| 122 | *strength = stat.signal_strength << 8; | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 127 | { | ||
| 128 | struct firedtv *fdtv = fe->sec_priv; | ||
| 129 | struct firedtv_tuner_status stat; | ||
| 130 | |||
| 131 | if (avc_tuner_status(fdtv, &stat)) | ||
| 132 | return -EINVAL; | ||
| 133 | |||
| 134 | /* C/N[dB] = -10 * log10(snr / 65535) */ | ||
| 135 | *snr = stat.carrier_noise_ratio * 257; | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 140 | { | ||
| 141 | return -EOPNOTSUPP; | ||
| 142 | } | ||
| 143 | |||
| 144 | #define ACCEPTED 0x9 | ||
| 145 | |||
| 146 | static int fdtv_set_frontend(struct dvb_frontend *fe, | ||
| 147 | struct dvb_frontend_parameters *params) | ||
| 148 | { | ||
| 149 | struct firedtv *fdtv = fe->sec_priv; | ||
| 150 | |||
| 151 | /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */ | ||
| 152 | if (avc_tuner_dsd(fdtv, params) != ACCEPTED) | ||
| 153 | return -EINVAL; | ||
| 154 | else | ||
| 155 | return 0; /* not sure of this... */ | ||
| 156 | } | ||
| 157 | |||
| 158 | static int fdtv_get_frontend(struct dvb_frontend *fe, | ||
| 159 | struct dvb_frontend_parameters *params) | ||
| 160 | { | ||
| 161 | return -EOPNOTSUPP; | ||
| 162 | } | ||
| 163 | |||
| 164 | void fdtv_frontend_init(struct firedtv *fdtv) | ||
| 165 | { | ||
| 166 | struct dvb_frontend_ops *ops = &fdtv->fe.ops; | ||
| 167 | struct dvb_frontend_info *fi = &ops->info; | ||
| 168 | |||
| 169 | ops->init = fdtv_dvb_init; | ||
| 170 | ops->sleep = fdtv_sleep; | ||
| 171 | |||
| 172 | ops->set_frontend = fdtv_set_frontend; | ||
| 173 | ops->get_frontend = fdtv_get_frontend; | ||
| 174 | |||
| 175 | ops->read_status = fdtv_read_status; | ||
| 176 | ops->read_ber = fdtv_read_ber; | ||
| 177 | ops->read_signal_strength = fdtv_read_signal_strength; | ||
| 178 | ops->read_snr = fdtv_read_snr; | ||
| 179 | ops->read_ucblocks = fdtv_read_uncorrected_blocks; | ||
| 180 | |||
| 181 | ops->diseqc_send_master_cmd = fdtv_diseqc_send_master_cmd; | ||
| 182 | ops->diseqc_send_burst = fdtv_diseqc_send_burst; | ||
| 183 | ops->set_tone = fdtv_set_tone; | ||
| 184 | ops->set_voltage = fdtv_set_voltage; | ||
| 185 | |||
| 186 | switch (fdtv->type) { | ||
| 187 | case FIREDTV_DVB_S: | ||
| 188 | case FIREDTV_DVB_S2: | ||
| 189 | fi->type = FE_QPSK; | ||
| 190 | |||
| 191 | fi->frequency_min = 950000; | ||
| 192 | fi->frequency_max = 2150000; | ||
| 193 | fi->frequency_stepsize = 125; | ||
| 194 | fi->symbol_rate_min = 1000000; | ||
| 195 | fi->symbol_rate_max = 40000000; | ||
| 196 | |||
| 197 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
| 198 | FE_CAN_FEC_1_2 | | ||
| 199 | FE_CAN_FEC_2_3 | | ||
| 200 | FE_CAN_FEC_3_4 | | ||
| 201 | FE_CAN_FEC_5_6 | | ||
| 202 | FE_CAN_FEC_7_8 | | ||
| 203 | FE_CAN_FEC_AUTO | | ||
| 204 | FE_CAN_QPSK; | ||
| 205 | break; | ||
| 206 | |||
| 207 | case FIREDTV_DVB_C: | ||
| 208 | fi->type = FE_QAM; | ||
| 209 | |||
| 210 | fi->frequency_min = 47000000; | ||
| 211 | fi->frequency_max = 866000000; | ||
| 212 | fi->frequency_stepsize = 62500; | ||
| 213 | fi->symbol_rate_min = 870000; | ||
| 214 | fi->symbol_rate_max = 6900000; | ||
| 215 | |||
| 216 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
| 217 | FE_CAN_QAM_16 | | ||
| 218 | FE_CAN_QAM_32 | | ||
| 219 | FE_CAN_QAM_64 | | ||
| 220 | FE_CAN_QAM_128 | | ||
| 221 | FE_CAN_QAM_256 | | ||
| 222 | FE_CAN_QAM_AUTO; | ||
| 223 | break; | ||
| 224 | |||
| 225 | case FIREDTV_DVB_T: | ||
| 226 | fi->type = FE_OFDM; | ||
| 227 | |||
| 228 | fi->frequency_min = 49000000; | ||
| 229 | fi->frequency_max = 861000000; | ||
| 230 | fi->frequency_stepsize = 62500; | ||
| 231 | |||
| 232 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
| 233 | FE_CAN_FEC_2_3 | | ||
| 234 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 235 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 236 | FE_CAN_HIERARCHY_AUTO; | ||
| 237 | break; | ||
| 238 | |||
| 239 | default: | ||
| 240 | dev_err(fdtv->device, "no frontend for model type %d\n", | ||
| 241 | fdtv->type); | ||
| 242 | } | ||
| 243 | strcpy(fi->name, fdtv_model_names[fdtv->type]); | ||
| 244 | |||
| 245 | fdtv->fe.dvb = &fdtv->adapter; | ||
| 246 | fdtv->fe.sec_priv = fdtv; | ||
| 247 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c new file mode 100644 index 00000000000..46a6324d7b7 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-rc.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation; either version 2 of | ||
| 9 | * the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/bitops.h> | ||
| 13 | #include <linux/input.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/string.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | |||
| 18 | #include "firedtv.h" | ||
| 19 | |||
| 20 | /* fixed table with older keycodes, geared towards MythTV */ | ||
| 21 | const static u16 oldtable[] = { | ||
| 22 | |||
| 23 | /* code from device: 0x4501...0x451f */ | ||
| 24 | |||
| 25 | KEY_ESC, | ||
| 26 | KEY_F9, | ||
| 27 | KEY_1, | ||
| 28 | KEY_2, | ||
| 29 | KEY_3, | ||
| 30 | KEY_4, | ||
| 31 | KEY_5, | ||
| 32 | KEY_6, | ||
| 33 | KEY_7, | ||
| 34 | KEY_8, | ||
| 35 | KEY_9, | ||
| 36 | KEY_I, | ||
| 37 | KEY_0, | ||
| 38 | KEY_ENTER, | ||
| 39 | KEY_RED, | ||
| 40 | KEY_UP, | ||
| 41 | KEY_GREEN, | ||
| 42 | KEY_F10, | ||
| 43 | KEY_SPACE, | ||
| 44 | KEY_F11, | ||
| 45 | KEY_YELLOW, | ||
| 46 | KEY_DOWN, | ||
| 47 | KEY_BLUE, | ||
| 48 | KEY_Z, | ||
| 49 | KEY_P, | ||
| 50 | KEY_PAGEDOWN, | ||
| 51 | KEY_LEFT, | ||
| 52 | KEY_W, | ||
| 53 | KEY_RIGHT, | ||
| 54 | KEY_P, | ||
| 55 | KEY_M, | ||
| 56 | |||
| 57 | /* code from device: 0x4540...0x4542 */ | ||
| 58 | |||
| 59 | KEY_R, | ||
| 60 | KEY_V, | ||
| 61 | KEY_C, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* user-modifiable table for a remote as sold in 2008 */ | ||
| 65 | const static u16 keytable[] = { | ||
| 66 | |||
| 67 | /* code from device: 0x0300...0x031f */ | ||
| 68 | |||
| 69 | [0x00] = KEY_POWER, | ||
| 70 | [0x01] = KEY_SLEEP, | ||
| 71 | [0x02] = KEY_STOP, | ||
| 72 | [0x03] = KEY_OK, | ||
| 73 | [0x04] = KEY_RIGHT, | ||
| 74 | [0x05] = KEY_1, | ||
| 75 | [0x06] = KEY_2, | ||
| 76 | [0x07] = KEY_3, | ||
| 77 | [0x08] = KEY_LEFT, | ||
| 78 | [0x09] = KEY_4, | ||
| 79 | [0x0a] = KEY_5, | ||
| 80 | [0x0b] = KEY_6, | ||
| 81 | [0x0c] = KEY_UP, | ||
| 82 | [0x0d] = KEY_7, | ||
| 83 | [0x0e] = KEY_8, | ||
| 84 | [0x0f] = KEY_9, | ||
| 85 | [0x10] = KEY_DOWN, | ||
| 86 | [0x11] = KEY_TITLE, /* "OSD" - fixme */ | ||
| 87 | [0x12] = KEY_0, | ||
| 88 | [0x13] = KEY_F20, /* "16:9" - fixme */ | ||
| 89 | [0x14] = KEY_SCREEN, /* "FULL" - fixme */ | ||
| 90 | [0x15] = KEY_MUTE, | ||
| 91 | [0x16] = KEY_SUBTITLE, | ||
| 92 | [0x17] = KEY_RECORD, | ||
| 93 | [0x18] = KEY_TEXT, | ||
| 94 | [0x19] = KEY_AUDIO, | ||
| 95 | [0x1a] = KEY_RED, | ||
| 96 | [0x1b] = KEY_PREVIOUS, | ||
| 97 | [0x1c] = KEY_REWIND, | ||
| 98 | [0x1d] = KEY_PLAYPAUSE, | ||
| 99 | [0x1e] = KEY_NEXT, | ||
| 100 | [0x1f] = KEY_VOLUMEUP, | ||
| 101 | |||
| 102 | /* code from device: 0x0340...0x0354 */ | ||
| 103 | |||
| 104 | [0x20] = KEY_CHANNELUP, | ||
| 105 | [0x21] = KEY_F21, /* "4:3" - fixme */ | ||
| 106 | [0x22] = KEY_TV, | ||
| 107 | [0x23] = KEY_DVD, | ||
| 108 | [0x24] = KEY_VCR, | ||
| 109 | [0x25] = KEY_AUX, | ||
| 110 | [0x26] = KEY_GREEN, | ||
| 111 | [0x27] = KEY_YELLOW, | ||
| 112 | [0x28] = KEY_BLUE, | ||
| 113 | [0x29] = KEY_CHANNEL, /* "CH.LIST" */ | ||
| 114 | [0x2a] = KEY_VENDOR, /* "CI" - fixme */ | ||
| 115 | [0x2b] = KEY_VOLUMEDOWN, | ||
| 116 | [0x2c] = KEY_CHANNELDOWN, | ||
| 117 | [0x2d] = KEY_LAST, | ||
| 118 | [0x2e] = KEY_INFO, | ||
| 119 | [0x2f] = KEY_FORWARD, | ||
| 120 | [0x30] = KEY_LIST, | ||
| 121 | [0x31] = KEY_FAVORITES, | ||
| 122 | [0x32] = KEY_MENU, | ||
| 123 | [0x33] = KEY_EPG, | ||
| 124 | [0x34] = KEY_EXIT, | ||
| 125 | }; | ||
| 126 | |||
| 127 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev) | ||
| 128 | { | ||
| 129 | struct input_dev *idev; | ||
| 130 | int i, err; | ||
| 131 | |||
| 132 | idev = input_allocate_device(); | ||
| 133 | if (!idev) | ||
| 134 | return -ENOMEM; | ||
| 135 | |||
| 136 | fdtv->remote_ctrl_dev = idev; | ||
| 137 | idev->name = "FireDTV remote control"; | ||
| 138 | idev->dev.parent = dev; | ||
| 139 | idev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 140 | idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL); | ||
| 141 | if (!idev->keycode) { | ||
| 142 | err = -ENOMEM; | ||
| 143 | goto fail; | ||
| 144 | } | ||
| 145 | idev->keycodesize = sizeof(keytable[0]); | ||
| 146 | idev->keycodemax = ARRAY_SIZE(keytable); | ||
| 147 | |||
| 148 | for (i = 0; i < ARRAY_SIZE(keytable); i++) | ||
| 149 | set_bit(keytable[i], idev->keybit); | ||
| 150 | |||
| 151 | err = input_register_device(idev); | ||
| 152 | if (err) | ||
| 153 | goto fail_free_keymap; | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | |||
| 157 | fail_free_keymap: | ||
| 158 | kfree(idev->keycode); | ||
| 159 | fail: | ||
| 160 | input_free_device(idev); | ||
| 161 | return err; | ||
| 162 | } | ||
| 163 | |||
| 164 | void fdtv_unregister_rc(struct firedtv *fdtv) | ||
| 165 | { | ||
| 166 | kfree(fdtv->remote_ctrl_dev->keycode); | ||
| 167 | input_unregister_device(fdtv->remote_ctrl_dev); | ||
| 168 | } | ||
| 169 | |||
| 170 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) | ||
| 171 | { | ||
| 172 | u16 *keycode = fdtv->remote_ctrl_dev->keycode; | ||
| 173 | |||
| 174 | if (code >= 0x0300 && code <= 0x031f) | ||
| 175 | code = keycode[code - 0x0300]; | ||
| 176 | else if (code >= 0x0340 && code <= 0x0354) | ||
| 177 | code = keycode[code - 0x0320]; | ||
| 178 | else if (code >= 0x4501 && code <= 0x451f) | ||
| 179 | code = oldtable[code - 0x4501]; | ||
| 180 | else if (code >= 0x4540 && code <= 0x4542) | ||
| 181 | code = oldtable[code - 0x4521]; | ||
| 182 | else { | ||
| 183 | printk(KERN_DEBUG "firedtv: invalid key code 0x%04x " | ||
| 184 | "from remote control\n", code); | ||
| 185 | return; | ||
| 186 | } | ||
| 187 | |||
| 188 | input_report_key(fdtv->remote_ctrl_dev, code, 1); | ||
| 189 | input_report_key(fdtv->remote_ctrl_dev, code, 0); | ||
| 190 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h new file mode 100644 index 00000000000..d48530b81e6 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv.h | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | /* | ||
| 2 | * FireDTV driver (formerly known as FireSAT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
| 5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation; either version 2 of | ||
| 10 | * the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _FIREDTV_H | ||
| 14 | #define _FIREDTV_H | ||
| 15 | |||
| 16 | #include <linux/dvb/dmx.h> | ||
| 17 | #include <linux/dvb/frontend.h> | ||
| 18 | #include <linux/list.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/spinlock_types.h> | ||
| 21 | #include <linux/types.h> | ||
| 22 | #include <linux/wait.h> | ||
| 23 | #include <linux/workqueue.h> | ||
| 24 | |||
| 25 | #include <demux.h> | ||
| 26 | #include <dmxdev.h> | ||
| 27 | #include <dvb_demux.h> | ||
| 28 | #include <dvb_frontend.h> | ||
| 29 | #include <dvb_net.h> | ||
| 30 | #include <dvbdev.h> | ||
| 31 | |||
| 32 | struct firedtv_tuner_status { | ||
| 33 | unsigned active_system:8; | ||
| 34 | unsigned searching:1; | ||
| 35 | unsigned moving:1; | ||
| 36 | unsigned no_rf:1; | ||
| 37 | unsigned input:1; | ||
| 38 | unsigned selected_antenna:7; | ||
| 39 | unsigned ber:32; | ||
| 40 | unsigned signal_strength:8; | ||
| 41 | unsigned raster_frequency:2; | ||
| 42 | unsigned rf_frequency:22; | ||
| 43 | unsigned man_dep_info_length:8; | ||
| 44 | unsigned front_end_error:1; | ||
| 45 | unsigned antenna_error:1; | ||
| 46 | unsigned front_end_power_status:1; | ||
| 47 | unsigned power_supply:1; | ||
| 48 | unsigned carrier_noise_ratio:16; | ||
| 49 | unsigned power_supply_voltage:8; | ||
| 50 | unsigned antenna_voltage:8; | ||
| 51 | unsigned firewire_bus_voltage:8; | ||
| 52 | unsigned ca_mmi:1; | ||
| 53 | unsigned ca_pmt_reply:1; | ||
| 54 | unsigned ca_date_time_request:1; | ||
| 55 | unsigned ca_application_info:1; | ||
| 56 | unsigned ca_module_present_status:1; | ||
| 57 | unsigned ca_dvb_flag:1; | ||
| 58 | unsigned ca_error_flag:1; | ||
| 59 | unsigned ca_initialization_status:1; | ||
| 60 | }; | ||
| 61 | |||
| 62 | enum model_type { | ||
| 63 | FIREDTV_UNKNOWN = 0, | ||
| 64 | FIREDTV_DVB_S = 1, | ||
| 65 | FIREDTV_DVB_C = 2, | ||
| 66 | FIREDTV_DVB_T = 3, | ||
| 67 | FIREDTV_DVB_S2 = 4, | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct device; | ||
| 71 | struct input_dev; | ||
| 72 | struct firedtv; | ||
| 73 | |||
| 74 | struct firedtv_backend { | ||
| 75 | int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg); | ||
| 76 | int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len); | ||
| 77 | int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); | ||
| 78 | int (*start_iso)(struct firedtv *fdtv); | ||
| 79 | void (*stop_iso)(struct firedtv *fdtv); | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct firedtv { | ||
| 83 | struct device *device; | ||
| 84 | struct list_head list; | ||
| 85 | |||
| 86 | struct dvb_adapter adapter; | ||
| 87 | struct dmxdev dmxdev; | ||
| 88 | struct dvb_demux demux; | ||
| 89 | struct dmx_frontend frontend; | ||
| 90 | struct dvb_net dvbnet; | ||
| 91 | struct dvb_frontend fe; | ||
| 92 | |||
| 93 | struct dvb_device *cadev; | ||
| 94 | int ca_last_command; | ||
| 95 | int ca_time_interval; | ||
| 96 | |||
| 97 | struct mutex avc_mutex; | ||
| 98 | wait_queue_head_t avc_wait; | ||
| 99 | bool avc_reply_received; | ||
| 100 | struct work_struct remote_ctrl_work; | ||
| 101 | struct input_dev *remote_ctrl_dev; | ||
| 102 | |||
| 103 | enum model_type type; | ||
| 104 | char subunit; | ||
| 105 | char isochannel; | ||
| 106 | fe_sec_voltage_t voltage; | ||
| 107 | fe_sec_tone_mode_t tone; | ||
| 108 | |||
| 109 | const struct firedtv_backend *backend; | ||
| 110 | void *backend_data; | ||
| 111 | |||
| 112 | struct mutex demux_mutex; | ||
| 113 | unsigned long channel_active; | ||
| 114 | u16 channel_pid[16]; | ||
| 115 | |||
| 116 | size_t response_length; | ||
| 117 | u8 response[512]; | ||
| 118 | }; | ||
| 119 | |||
| 120 | /* firedtv-1394.c */ | ||
| 121 | #ifdef CONFIG_DVB_FIREDTV_IEEE1394 | ||
| 122 | int fdtv_1394_init(struct ieee1394_device_id id_table[]); | ||
| 123 | void fdtv_1394_exit(void); | ||
| 124 | #else | ||
| 125 | static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; } | ||
| 126 | static inline void fdtv_1394_exit(void) {} | ||
| 127 | #endif | ||
| 128 | |||
| 129 | /* firedtv-avc.c */ | ||
| 130 | int avc_recv(struct firedtv *fdtv, void *data, size_t length); | ||
| 131 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat); | ||
| 132 | struct dvb_frontend_parameters; | ||
| 133 | int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params); | ||
| 134 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]); | ||
| 135 | int avc_tuner_get_ts(struct firedtv *fdtv); | ||
| 136 | int avc_identify_subunit(struct firedtv *fdtv); | ||
| 137 | struct dvb_diseqc_master_cmd; | ||
| 138 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
| 139 | char conttone, char nrdiseq, | ||
| 140 | struct dvb_diseqc_master_cmd *diseqcmd); | ||
| 141 | void avc_remote_ctrl_work(struct work_struct *work); | ||
| 142 | int avc_register_remote_control(struct firedtv *fdtv); | ||
| 143 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
| 144 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
| 145 | int avc_ca_reset(struct firedtv *fdtv); | ||
| 146 | int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length); | ||
| 147 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval); | ||
| 148 | int avc_ca_enter_menu(struct firedtv *fdtv); | ||
| 149 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len); | ||
| 150 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
| 151 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
| 152 | |||
| 153 | /* firedtv-ci.c */ | ||
| 154 | int fdtv_ca_register(struct firedtv *fdtv); | ||
| 155 | void fdtv_ca_release(struct firedtv *fdtv); | ||
| 156 | |||
| 157 | /* firedtv-dvb.c */ | ||
| 158 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
| 159 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
| 160 | int fdtv_dvb_register(struct firedtv *fdtv); | ||
| 161 | void fdtv_dvb_unregister(struct firedtv *fdtv); | ||
| 162 | struct firedtv *fdtv_alloc(struct device *dev, | ||
| 163 | const struct firedtv_backend *backend, | ||
| 164 | const char *name, size_t name_len); | ||
| 165 | extern const char *fdtv_model_names[]; | ||
| 166 | |||
| 167 | /* firedtv-fe.c */ | ||
| 168 | void fdtv_frontend_init(struct firedtv *fdtv); | ||
| 169 | |||
| 170 | /* firedtv-rc.c */ | ||
| 171 | #ifdef CONFIG_DVB_FIREDTV_INPUT | ||
| 172 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev); | ||
| 173 | void fdtv_unregister_rc(struct firedtv *fdtv); | ||
| 174 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code); | ||
| 175 | #else | ||
| 176 | static inline int fdtv_register_rc(struct firedtv *fdtv, | ||
| 177 | struct device *dev) { return 0; } | ||
| 178 | static inline void fdtv_unregister_rc(struct firedtv *fdtv) {} | ||
| 179 | static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {} | ||
| 180 | #endif | ||
| 181 | |||
| 182 | #endif /* _FIREDTV_H */ | ||
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 5d882a44e3e..2ac738fa6a0 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
| @@ -463,6 +463,8 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
| 463 | pcm->info_flags = 0; | 463 | pcm->info_flags = 0; |
| 464 | pcm->private_data = dev; | 464 | pcm->private_data = dev; |
| 465 | strcpy(pcm->name, "Empia 28xx Capture"); | 465 | strcpy(pcm->name, "Empia 28xx Capture"); |
| 466 | |||
| 467 | snd_card_set_dev(card, &dev->udev->dev); | ||
| 466 | strcpy(card->driver, "Empia Em28xx Audio"); | 468 | strcpy(card->driver, "Empia Em28xx Audio"); |
| 467 | strcpy(card->shortname, "Em28xx Audio"); | 469 | strcpy(card->shortname, "Em28xx Audio"); |
| 468 | strcpy(card->longname, "Empia Em28xx Audio"); | 470 | strcpy(card->longname, "Empia Em28xx Audio"); |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a1d6008efcb..07c334f25aa 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
| @@ -1155,23 +1155,23 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
| 1155 | { | 1155 | { |
| 1156 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1156 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
| 1157 | struct pxa_camera_dev *pcdev = ici->priv; | 1157 | struct pxa_camera_dev *pcdev = ici->priv; |
| 1158 | const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; | 1158 | const struct soc_camera_data_format *cam_fmt = NULL; |
| 1159 | const struct soc_camera_format_xlate *xlate; | 1159 | const struct soc_camera_format_xlate *xlate = NULL; |
| 1160 | struct soc_camera_sense sense = { | 1160 | struct soc_camera_sense sense = { |
| 1161 | .master_clock = pcdev->mclk, | 1161 | .master_clock = pcdev->mclk, |
| 1162 | .pixel_clock_max = pcdev->ciclk / 4, | 1162 | .pixel_clock_max = pcdev->ciclk / 4, |
| 1163 | }; | 1163 | }; |
| 1164 | int ret, buswidth; | 1164 | int ret; |
| 1165 | 1165 | ||
| 1166 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1166 | if (pixfmt) { |
| 1167 | if (!xlate) { | 1167 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
| 1168 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); | 1168 | if (!xlate) { |
| 1169 | return -EINVAL; | 1169 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); |
| 1170 | } | 1170 | return -EINVAL; |
| 1171 | } | ||
| 1171 | 1172 | ||
| 1172 | buswidth = xlate->buswidth; | 1173 | cam_fmt = xlate->cam_fmt; |
| 1173 | host_fmt = xlate->host_fmt; | 1174 | } |
| 1174 | cam_fmt = xlate->cam_fmt; | ||
| 1175 | 1175 | ||
| 1176 | /* If PCLK is used to latch data from the sensor, check sense */ | 1176 | /* If PCLK is used to latch data from the sensor, check sense */ |
| 1177 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 1177 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
| @@ -1201,8 +1201,8 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
| 1201 | } | 1201 | } |
| 1202 | 1202 | ||
| 1203 | if (pixfmt && !ret) { | 1203 | if (pixfmt && !ret) { |
| 1204 | icd->buswidth = buswidth; | 1204 | icd->buswidth = xlate->buswidth; |
| 1205 | icd->current_fmt = host_fmt; | 1205 | icd->current_fmt = xlate->host_fmt; |
| 1206 | } | 1206 | } |
| 1207 | 1207 | ||
| 1208 | return ret; | 1208 | return ret; |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9a2586b07a0..ddcb81d0b81 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
| @@ -603,21 +603,18 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
| 603 | const struct soc_camera_format_xlate *xlate; | 603 | const struct soc_camera_format_xlate *xlate; |
| 604 | int ret; | 604 | int ret; |
| 605 | 605 | ||
| 606 | if (!pixfmt) | ||
| 607 | return icd->ops->set_fmt(icd, pixfmt, rect); | ||
| 608 | |||
| 606 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 609 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
| 607 | if (!xlate) { | 610 | if (!xlate) { |
| 608 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); | 611 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); |
| 609 | return -EINVAL; | 612 | return -EINVAL; |
| 610 | } | 613 | } |
| 611 | 614 | ||
| 612 | switch (pixfmt) { | 615 | ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); |
| 613 | case 0: /* Only geometry change */ | ||
| 614 | ret = icd->ops->set_fmt(icd, pixfmt, rect); | ||
| 615 | break; | ||
| 616 | default: | ||
| 617 | ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); | ||
| 618 | } | ||
| 619 | 616 | ||
| 620 | if (pixfmt && !ret) { | 617 | if (!ret) { |
| 621 | icd->buswidth = xlate->buswidth; | 618 | icd->buswidth = xlate->buswidth; |
| 622 | icd->current_fmt = xlate->host_fmt; | 619 | icd->current_fmt = xlate->host_fmt; |
| 623 | pcdev->camera_fmt = xlate->cam_fmt; | 620 | pcdev->camera_fmt = xlate->cam_fmt; |
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index c1e4ae27c61..c705f248da8 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c | |||
| @@ -46,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev) | |||
| 46 | usb_to_input_id(udev, &input->id); | 46 | usb_to_input_id(udev, &input->id); |
| 47 | input->dev.parent = &dev->intf->dev; | 47 | input->dev.parent = &dev->intf->dev; |
| 48 | 48 | ||
| 49 | set_bit(EV_KEY, input->evbit); | 49 | __set_bit(EV_KEY, input->evbit); |
| 50 | set_bit(BTN_0, input->keybit); | 50 | __set_bit(KEY_CAMERA, input->keybit); |
| 51 | 51 | ||
| 52 | if ((ret = input_register_device(input)) < 0) | 52 | if ((ret = input_register_device(input)) < 0) |
| 53 | goto error; | 53 | goto error; |
| @@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) | |||
| 70 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, | 70 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, |
| 71 | int value) | 71 | int value) |
| 72 | { | 72 | { |
| 73 | if (dev->input) | 73 | if (dev->input) { |
| 74 | input_report_key(dev->input, code, value); | 74 | input_report_key(dev->input, code, value); |
| 75 | input_sync(dev->input); | ||
| 76 | } | ||
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | #else | 79 | #else |
| @@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) | |||
| 96 | return; | 98 | return; |
| 97 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", | 99 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", |
| 98 | data[1], data[3] ? "pressed" : "released", len); | 100 | data[1], data[3] ? "pressed" : "released", len); |
| 99 | uvc_input_report_key(dev, BTN_0, data[3]); | 101 | uvc_input_report_key(dev, KEY_CAMERA, data[3]); |
| 100 | } else { | 102 | } else { |
| 101 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " | 103 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " |
| 102 | "len %d.\n", data[1], data[2], data[3], len); | 104 | "len %d.\n", data[1], data[2], data[3], len); |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 96ac88317b8..ea3aafbbda4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -91,9 +91,9 @@ MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \ | |||
| 91 | controllers (default=0)"); | 91 | controllers (default=0)"); |
| 92 | 92 | ||
| 93 | static int mpt_msi_enable_sas; | 93 | static int mpt_msi_enable_sas; |
| 94 | module_param(mpt_msi_enable_sas, int, 1); | 94 | module_param(mpt_msi_enable_sas, int, 0); |
| 95 | MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ | 95 | MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ |
| 96 | controllers (default=1)"); | 96 | controllers (default=0)"); |
| 97 | 97 | ||
| 98 | 98 | ||
| 99 | static int mpt_channel_mapping; | 99 | static int mpt_channel_mapping; |
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index f26667a7abf..cf991850f01 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
| @@ -710,6 +710,7 @@ out: | |||
| 710 | 710 | ||
| 711 | static struct pci_device_id ilo_devices[] = { | 711 | static struct pci_device_id ilo_devices[] = { |
| 712 | { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) }, | 712 | { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) }, |
| 713 | { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3307) }, | ||
| 713 | { } | 714 | { } |
| 714 | }; | 715 | }; |
| 715 | MODULE_DEVICE_TABLE(pci, ilo_devices); | 716 | MODULE_DEVICE_TABLE(pci, ilo_devices); |
| @@ -758,7 +759,7 @@ static void __exit ilo_exit(void) | |||
| 758 | class_destroy(ilo_class); | 759 | class_destroy(ilo_class); |
| 759 | } | 760 | } |
| 760 | 761 | ||
| 761 | MODULE_VERSION("0.06"); | 762 | MODULE_VERSION("1.0"); |
| 762 | MODULE_ALIAS(ILO_NAME); | 763 | MODULE_ALIAS(ILO_NAME); |
| 763 | MODULE_DESCRIPTION(ILO_NAME); | 764 | MODULE_DESCRIPTION(ILO_NAME); |
| 764 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); | 765 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8cff5f5e7f8..406da9a8d45 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -107,6 +107,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { | |||
| 107 | 107 | ||
| 108 | static const struct sdhci_pci_fixes sdhci_cafe = { | 108 | static const struct sdhci_pci_fixes sdhci_cafe = { |
| 109 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | 109 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | |
| 110 | SDHCI_QUIRK_NO_BUSY_IRQ | | ||
| 110 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, | 111 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, |
| 111 | }; | 112 | }; |
| 112 | 113 | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f52f3053ed9..accb592764e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -1291,8 +1291,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
| 1291 | if (host->cmd->data) | 1291 | if (host->cmd->data) |
| 1292 | DBG("Cannot wait for busy signal when also " | 1292 | DBG("Cannot wait for busy signal when also " |
| 1293 | "doing a data transfer"); | 1293 | "doing a data transfer"); |
| 1294 | else | 1294 | else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) |
| 1295 | return; | 1295 | return; |
| 1296 | |||
| 1297 | /* The controller does not support the end-of-busy IRQ, | ||
| 1298 | * fall through and take the SDHCI_INT_RESPONSE */ | ||
| 1296 | } | 1299 | } |
| 1297 | 1300 | ||
| 1298 | if (intmask & SDHCI_INT_RESPONSE) | 1301 | if (intmask & SDHCI_INT_RESPONSE) |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index ebb83657e27..43c37c68d07 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -208,6 +208,8 @@ struct sdhci_host { | |||
| 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) |
| 209 | /* Controller has an issue with buffer bits for small transfers */ | 209 | /* Controller has an issue with buffer bits for small transfers */ |
| 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) |
| 211 | /* Controller does not provide transfer-complete interrupt when not busy */ | ||
| 212 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | ||
| 211 | 213 | ||
| 212 | int irq; /* Device IRQ */ | 214 | int irq; /* Device IRQ */ |
| 213 | void __iomem * ioaddr; /* Mapped address */ | 215 | void __iomem * ioaddr; /* Mapped address */ |
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 821d0ed6bae..c76d6e5f47e 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
| @@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | |||
| 19 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 19 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
| 20 | static void maprom_nop (struct mtd_info *); | 20 | static void maprom_nop (struct mtd_info *); |
| 21 | static struct mtd_info *map_rom_probe(struct map_info *map); | 21 | static struct mtd_info *map_rom_probe(struct map_info *map); |
| 22 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info); | ||
| 22 | 23 | ||
| 23 | static struct mtd_chip_driver maprom_chipdrv = { | 24 | static struct mtd_chip_driver maprom_chipdrv = { |
| 24 | .probe = map_rom_probe, | 25 | .probe = map_rom_probe, |
| @@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map) | |||
| 42 | mtd->read = maprom_read; | 43 | mtd->read = maprom_read; |
| 43 | mtd->write = maprom_write; | 44 | mtd->write = maprom_write; |
| 44 | mtd->sync = maprom_nop; | 45 | mtd->sync = maprom_nop; |
| 46 | mtd->erase = maprom_erase; | ||
| 45 | mtd->flags = MTD_CAP_ROM; | 47 | mtd->flags = MTD_CAP_ROM; |
| 46 | mtd->erasesize = map->size; | 48 | mtd->erasesize = map->size; |
| 47 | mtd->writesize = 1; | 49 | mtd->writesize = 1; |
| @@ -71,6 +73,12 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re | |||
| 71 | return -EIO; | 73 | return -EIO; |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 76 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info) | ||
| 77 | { | ||
| 78 | /* We do our best 8) */ | ||
| 79 | return -EROFS; | ||
| 80 | } | ||
| 81 | |||
| 74 | static int __init map_rom_init(void) | 82 | static int __init map_rom_init(void) |
| 75 | { | 83 | { |
| 76 | register_mtd_chip_driver(&maprom_chipdrv); | 84 | register_mtd_chip_driver(&maprom_chipdrv); |
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index a425d09f35a..00248e81ecd 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c | |||
| @@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) | |||
| 267 | if (*(szlength) != '+') { | 267 | if (*(szlength) != '+') { |
| 268 | devlength = simple_strtoul(szlength, &buffer, 0); | 268 | devlength = simple_strtoul(szlength, &buffer, 0); |
| 269 | devlength = handle_unit(devlength, buffer) - devstart; | 269 | devlength = handle_unit(devlength, buffer) - devstart; |
| 270 | if (devlength < devstart) | ||
| 271 | goto err_out; | ||
| 272 | |||
| 273 | devlength -= devstart; | ||
| 270 | } else { | 274 | } else { |
| 271 | devlength = simple_strtoul(szlength + 1, &buffer, 0); | 275 | devlength = simple_strtoul(szlength + 1, &buffer, 0); |
| 272 | devlength = handle_unit(devlength, buffer); | 276 | devlength = handle_unit(devlength, buffer); |
| 273 | } | 277 | } |
| 274 | T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", | 278 | T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", |
| 275 | devname, devstart, devlength); | 279 | devname, devstart, devlength); |
| 276 | if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) { | 280 | if (devlength % SLRAM_BLK_SZ != 0) |
| 277 | E("slram: Illegal start / length parameter.\n"); | 281 | goto err_out; |
| 278 | return(-EINVAL); | ||
| 279 | } | ||
| 280 | 282 | ||
| 281 | if ((devstart = register_device(devname, devstart, devlength))){ | 283 | if ((devstart = register_device(devname, devstart, devlength))){ |
| 282 | unregister_devices(); | 284 | unregister_devices(); |
| 283 | return((int)devstart); | 285 | return((int)devstart); |
| 284 | } | 286 | } |
| 285 | return(0); | 287 | return(0); |
| 288 | |||
| 289 | err_out: | ||
| 290 | E("slram: Illegal length parameter.\n"); | ||
| 291 | return(-EINVAL); | ||
| 286 | } | 292 | } |
| 287 | 293 | ||
| 288 | #ifndef MODULE | 294 | #ifndef MODULE |
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig index acd4ea9b227..5a401d8047a 100644 --- a/drivers/mtd/lpddr/Kconfig +++ b/drivers/mtd/lpddr/Kconfig | |||
| @@ -12,6 +12,7 @@ config MTD_LPDDR | |||
| 12 | DDR memories, intended for battery-operated systems. | 12 | DDR memories, intended for battery-operated systems. |
| 13 | 13 | ||
| 14 | config MTD_QINFO_PROBE | 14 | config MTD_QINFO_PROBE |
| 15 | depends on MTD_LPDDR | ||
| 15 | tristate "Detect flash chips by QINFO probe" | 16 | tristate "Detect flash chips by QINFO probe" |
| 16 | help | 17 | help |
| 17 | Device Information for LPDDR chips is offered through the Overlay | 18 | Device Information for LPDDR chips is offered through the Overlay |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 0225cbbf22d..043d50fb6ef 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
| @@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS | |||
| 491 | 491 | ||
| 492 | config MTD_BFIN_ASYNC | 492 | config MTD_BFIN_ASYNC |
| 493 | tristate "Blackfin BF533-STAMP Flash Chip Support" | 493 | tristate "Blackfin BF533-STAMP Flash Chip Support" |
| 494 | depends on BFIN533_STAMP && MTD_CFI | 494 | depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS |
| 495 | select MTD_PARTITIONS | 495 | select MTD_PARTITIONS |
| 496 | default y | 496 | default y |
| 497 | help | 497 | help |
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 6fec86aaed7..576611f605d 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
| @@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) | |||
| 152 | 152 | ||
| 153 | if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) { | 153 | if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) { |
| 154 | pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin); | 154 | pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin); |
| 155 | kfree(state); | ||
| 155 | return -EBUSY; | 156 | return -EBUSY; |
| 156 | } | 157 | } |
| 157 | gpio_direction_output(state->enet_flash_pin, 1); | 158 | gpio_direction_output(state->enet_flash_pin, 1); |
| 158 | 159 | ||
| 159 | pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8); | 160 | pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8); |
| 160 | state->mtd = do_map_probe(memory->name, &state->map); | 161 | state->mtd = do_map_probe(memory->name, &state->map); |
| 161 | if (!state->mtd) | 162 | if (!state->mtd) { |
| 163 | gpio_free(state->enet_flash_pin); | ||
| 164 | kfree(state); | ||
| 162 | return -ENXIO; | 165 | return -ENXIO; |
| 166 | } | ||
| 163 | 167 | ||
| 164 | #ifdef CONFIG_MTD_PARTITIONS | 168 | #ifdef CONFIG_MTD_PARTITIONS |
| 165 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); | 169 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); |
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 5f7a245ed13..424f17d6ffd 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c | |||
| @@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = { | |||
| 342 | { 0, } | 342 | { 0, } |
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| 345 | #if 0 | ||
| 345 | MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl); | 346 | MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl); |
| 346 | 347 | ||
| 347 | #if 0 | ||
| 348 | static struct pci_driver ck804xrom_driver = { | 348 | static struct pci_driver ck804xrom_driver = { |
| 349 | .name = MOD_NAME, | 349 | .name = MOD_NAME, |
| 350 | .id_table = ck804xrom_pci_tbl, | 350 | .id_table = ck804xrom_pci_tbl, |
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 87743661d48..4b122e7ab4b 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
| @@ -29,6 +29,7 @@ struct physmap_flash_info { | |||
| 29 | struct map_info map[MAX_RESOURCES]; | 29 | struct map_info map[MAX_RESOURCES]; |
| 30 | #ifdef CONFIG_MTD_PARTITIONS | 30 | #ifdef CONFIG_MTD_PARTITIONS |
| 31 | int nr_parts; | 31 | int nr_parts; |
| 32 | struct mtd_partition *parts; | ||
| 32 | #endif | 33 | #endif |
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| @@ -45,25 +46,26 @@ static int physmap_flash_remove(struct platform_device *dev) | |||
| 45 | 46 | ||
| 46 | physmap_data = dev->dev.platform_data; | 47 | physmap_data = dev->dev.platform_data; |
| 47 | 48 | ||
| 48 | #ifdef CONFIG_MTD_CONCAT | 49 | #ifdef CONFIG_MTD_PARTITIONS |
| 49 | if (info->cmtd != info->mtd[0]) { | 50 | if (info->nr_parts) { |
| 51 | del_mtd_partitions(info->cmtd); | ||
| 52 | kfree(info->parts); | ||
| 53 | } else if (physmap_data->nr_parts) | ||
| 54 | del_mtd_partitions(info->cmtd); | ||
| 55 | else | ||
| 50 | del_mtd_device(info->cmtd); | 56 | del_mtd_device(info->cmtd); |
| 57 | #else | ||
| 58 | del_mtd_device(info->cmtd); | ||
| 59 | #endif | ||
| 60 | |||
| 61 | #ifdef CONFIG_MTD_CONCAT | ||
| 62 | if (info->cmtd != info->mtd[0]) | ||
| 51 | mtd_concat_destroy(info->cmtd); | 63 | mtd_concat_destroy(info->cmtd); |
| 52 | } | ||
| 53 | #endif | 64 | #endif |
| 54 | 65 | ||
| 55 | for (i = 0; i < MAX_RESOURCES; i++) { | 66 | for (i = 0; i < MAX_RESOURCES; i++) { |
| 56 | if (info->mtd[i] != NULL) { | 67 | if (info->mtd[i] != NULL) |
| 57 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 58 | if (info->nr_parts || physmap_data->nr_parts) | ||
| 59 | del_mtd_partitions(info->mtd[i]); | ||
| 60 | else | ||
| 61 | del_mtd_device(info->mtd[i]); | ||
| 62 | #else | ||
| 63 | del_mtd_device(info->mtd[i]); | ||
| 64 | #endif | ||
| 65 | map_destroy(info->mtd[i]); | 68 | map_destroy(info->mtd[i]); |
| 66 | } | ||
| 67 | } | 69 | } |
| 68 | return 0; | 70 | return 0; |
| 69 | } | 71 | } |
| @@ -86,9 +88,6 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
| 86 | int err = 0; | 88 | int err = 0; |
| 87 | int i; | 89 | int i; |
| 88 | int devices_found = 0; | 90 | int devices_found = 0; |
| 89 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 90 | struct mtd_partition *parts; | ||
| 91 | #endif | ||
| 92 | 91 | ||
| 93 | physmap_data = dev->dev.platform_data; | 92 | physmap_data = dev->dev.platform_data; |
| 94 | if (physmap_data == NULL) | 93 | if (physmap_data == NULL) |
| @@ -167,10 +166,11 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
| 167 | goto err_out; | 166 | goto err_out; |
| 168 | 167 | ||
| 169 | #ifdef CONFIG_MTD_PARTITIONS | 168 | #ifdef CONFIG_MTD_PARTITIONS |
| 170 | err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0); | 169 | err = parse_mtd_partitions(info->cmtd, part_probe_types, |
| 170 | &info->parts, 0); | ||
| 171 | if (err > 0) { | 171 | if (err > 0) { |
| 172 | add_mtd_partitions(info->cmtd, parts, err); | 172 | add_mtd_partitions(info->cmtd, info->parts, err); |
| 173 | kfree(parts); | 173 | info->nr_parts = err; |
| 174 | return 0; | 174 | return 0; |
| 175 | } | 175 | } |
| 176 | 176 | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 917cf8d3ae9..c2dfd3ea353 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
| @@ -149,7 +149,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) | |||
| 149 | 149 | ||
| 150 | static struct platform_driver orion_nand_driver = { | 150 | static struct platform_driver orion_nand_driver = { |
| 151 | .probe = orion_nand_probe, | 151 | .probe = orion_nand_probe, |
| 152 | .remove = orion_nand_remove, | 152 | .remove = __devexit_p(orion_nand_remove), |
| 153 | .driver = { | 153 | .driver = { |
| 154 | .name = "orion_nand", | 154 | .name = "orion_nand", |
| 155 | .owner = THIS_MODULE, | 155 | .owner = THIS_MODULE, |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6bdfd47d679..a2f185fd707 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -2342,6 +2342,17 @@ config ATL1E | |||
| 2342 | To compile this driver as a module, choose M here. The module | 2342 | To compile this driver as a module, choose M here. The module |
| 2343 | will be called atl1e. | 2343 | will be called atl1e. |
| 2344 | 2344 | ||
| 2345 | config ATL1C | ||
| 2346 | tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)" | ||
| 2347 | depends on PCI && EXPERIMENTAL | ||
| 2348 | select CRC32 | ||
| 2349 | select MII | ||
| 2350 | help | ||
| 2351 | This driver supports the Atheros L1C gigabit ethernet adapter. | ||
| 2352 | |||
| 2353 | To compile this driver as a module, choose M here. The module | ||
| 2354 | will be called atl1c. | ||
| 2355 | |||
| 2345 | config JME | 2356 | config JME |
| 2346 | tristate "JMicron(R) PCI-Express Gigabit Ethernet support" | 2357 | tristate "JMicron(R) PCI-Express Gigabit Ethernet support" |
| 2347 | depends on PCI | 2358 | depends on PCI |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a3c5c002f22..aca8492db65 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
| @@ -17,6 +17,7 @@ obj-$(CONFIG_BONDING) += bonding/ | |||
| 17 | obj-$(CONFIG_ATL1) += atlx/ | 17 | obj-$(CONFIG_ATL1) += atlx/ |
| 18 | obj-$(CONFIG_ATL2) += atlx/ | 18 | obj-$(CONFIG_ATL2) += atlx/ |
| 19 | obj-$(CONFIG_ATL1E) += atl1e/ | 19 | obj-$(CONFIG_ATL1E) += atl1e/ |
| 20 | obj-$(CONFIG_ATL1C) += atl1c/ | ||
| 20 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o | 21 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o |
| 21 | obj-$(CONFIG_TEHUTI) += tehuti.o | 22 | obj-$(CONFIG_TEHUTI) += tehuti.o |
| 22 | obj-$(CONFIG_ENIC) += enic/ | 23 | obj-$(CONFIG_ENIC) += enic/ |
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index c69c0cdba4a..811a3ccd14c 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o | 6 | obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o |
| 7 | obj-$(CONFIG_ARM_ETHERH) += etherh.o ../8390.o | 7 | obj-$(CONFIG_ARM_ETHERH) += etherh.o |
| 8 | obj-$(CONFIG_ARM_ETHER3) += ether3.o | 8 | obj-$(CONFIG_ARM_ETHER3) += ether3.o |
| 9 | obj-$(CONFIG_ARM_ETHER1) += ether1.o | 9 | obj-$(CONFIG_ARM_ETHER1) += ether1.o |
| 10 | obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o | 10 | obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o |
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 54b52e5b182..f52f668c49b 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c | |||
| @@ -641,15 +641,15 @@ static const struct net_device_ops etherh_netdev_ops = { | |||
| 641 | .ndo_open = etherh_open, | 641 | .ndo_open = etherh_open, |
| 642 | .ndo_stop = etherh_close, | 642 | .ndo_stop = etherh_close, |
| 643 | .ndo_set_config = etherh_set_config, | 643 | .ndo_set_config = etherh_set_config, |
| 644 | .ndo_start_xmit = ei_start_xmit, | 644 | .ndo_start_xmit = __ei_start_xmit, |
| 645 | .ndo_tx_timeout = ei_tx_timeout, | 645 | .ndo_tx_timeout = __ei_tx_timeout, |
| 646 | .ndo_get_stats = ei_get_stats, | 646 | .ndo_get_stats = __ei_get_stats, |
| 647 | .ndo_set_multicast_list = ei_set_multicast_list, | 647 | .ndo_set_multicast_list = __ei_set_multicast_list, |
| 648 | .ndo_validate_addr = eth_validate_addr, | 648 | .ndo_validate_addr = eth_validate_addr, |
| 649 | .ndo_set_mac_address = eth_mac_addr, | 649 | .ndo_set_mac_address = eth_mac_addr, |
| 650 | .ndo_change_mtu = eth_change_mtu, | 650 | .ndo_change_mtu = eth_change_mtu, |
| 651 | #ifdef CONFIG_NET_POLL_CONTROLLER | 651 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 652 | .ndo_poll_controller = ei_poll, | 652 | .ndo_poll_controller = __ei_poll, |
| 653 | #endif | 653 | #endif |
| 654 | }; | 654 | }; |
| 655 | 655 | ||
diff --git a/drivers/net/atl1c/Makefile b/drivers/net/atl1c/Makefile new file mode 100644 index 00000000000..c37d966952e --- /dev/null +++ b/drivers/net/atl1c/Makefile | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | obj-$(CONFIG_ATL1C) += atl1c.o | ||
| 2 | atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o | ||
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h new file mode 100644 index 00000000000..ac11b84b837 --- /dev/null +++ b/drivers/net/atl1c/atl1c.h | |||
| @@ -0,0 +1,606 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Derived from Intel e1000 driver | ||
| 5 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _ATL1C_H_ | ||
| 23 | #define _ATL1C_H_ | ||
| 24 | |||
| 25 | #include <linux/version.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/errno.h> | ||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/pci.h> | ||
| 31 | #include <linux/netdevice.h> | ||
| 32 | #include <linux/etherdevice.h> | ||
| 33 | #include <linux/skbuff.h> | ||
| 34 | #include <linux/ioport.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | #include <linux/list.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/sched.h> | ||
| 39 | #include <linux/in.h> | ||
| 40 | #include <linux/ip.h> | ||
| 41 | #include <linux/ipv6.h> | ||
| 42 | #include <linux/udp.h> | ||
| 43 | #include <linux/mii.h> | ||
| 44 | #include <linux/io.h> | ||
| 45 | #include <linux/vmalloc.h> | ||
| 46 | #include <linux/pagemap.h> | ||
| 47 | #include <linux/tcp.h> | ||
| 48 | #include <linux/mii.h> | ||
| 49 | #include <linux/ethtool.h> | ||
| 50 | #include <linux/if_vlan.h> | ||
| 51 | #include <linux/workqueue.h> | ||
| 52 | #include <net/checksum.h> | ||
| 53 | #include <net/ip6_checksum.h> | ||
| 54 | |||
| 55 | #include "atl1c_hw.h" | ||
| 56 | |||
| 57 | /* Wake Up Filter Control */ | ||
| 58 | #define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ | ||
| 59 | #define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ | ||
| 60 | #define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ | ||
| 61 | #define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ | ||
| 62 | #define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ | ||
| 63 | |||
| 64 | #define AT_VLAN_TO_TAG(_vlan, _tag) \ | ||
| 65 | _tag = ((((_vlan) >> 8) & 0xFF) |\ | ||
| 66 | (((_vlan) & 0xFF) << 8)) | ||
| 67 | |||
| 68 | #define AT_TAG_TO_VLAN(_tag, _vlan) \ | ||
| 69 | _vlan = ((((_tag) >> 8) & 0xFF) |\ | ||
| 70 | (((_tag) & 0xFF) << 8)) | ||
| 71 | |||
| 72 | #define SPEED_0 0xffff | ||
| 73 | #define HALF_DUPLEX 1 | ||
| 74 | #define FULL_DUPLEX 2 | ||
| 75 | |||
| 76 | #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) | ||
| 77 | #define MAX_JUMBO_FRAME_SIZE (9*1024) | ||
| 78 | #define MAX_TX_OFFLOAD_THRESH (9*1024) | ||
| 79 | |||
| 80 | #define AT_MAX_RECEIVE_QUEUE 4 | ||
| 81 | #define AT_DEF_RECEIVE_QUEUE 1 | ||
| 82 | #define AT_MAX_TRANSMIT_QUEUE 2 | ||
| 83 | |||
| 84 | #define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL | ||
| 85 | #define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL | ||
| 86 | |||
| 87 | #define AT_TX_WATCHDOG (5 * HZ) | ||
| 88 | #define AT_MAX_INT_WORK 5 | ||
| 89 | #define AT_TWSI_EEPROM_TIMEOUT 100 | ||
| 90 | #define AT_HW_MAX_IDLE_DELAY 10 | ||
| 91 | #define AT_SUSPEND_LINK_TIMEOUT 28 | ||
| 92 | |||
| 93 | #define AT_ASPM_L0S_TIMER 6 | ||
| 94 | #define AT_ASPM_L1_TIMER 12 | ||
| 95 | |||
| 96 | #define ATL1C_PCIE_L0S_L1_DISABLE 0x01 | ||
| 97 | #define ATL1C_PCIE_PHY_RESET 0x02 | ||
| 98 | |||
| 99 | #define ATL1C_ASPM_L0s_ENABLE 0x0001 | ||
| 100 | #define ATL1C_ASPM_L1_ENABLE 0x0002 | ||
| 101 | |||
| 102 | #define AT_REGS_LEN (75 * sizeof(u32)) | ||
| 103 | #define AT_EEPROM_LEN 512 | ||
| 104 | |||
| 105 | #define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) | ||
| 106 | #define ATL1C_RFD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc) | ||
| 107 | #define ATL1C_TPD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc) | ||
| 108 | #define ATL1C_RRD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status) | ||
| 109 | |||
| 110 | /* tpd word 1 bit 0:7 General Checksum task offload */ | ||
| 111 | #define TPD_L4HDR_OFFSET_MASK 0x00FF | ||
| 112 | #define TPD_L4HDR_OFFSET_SHIFT 0 | ||
| 113 | |||
| 114 | /* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */ | ||
| 115 | #define TPD_TCPHDR_OFFSET_MASK 0x00FF | ||
| 116 | #define TPD_TCPHDR_OFFSET_SHIFT 0 | ||
| 117 | |||
| 118 | /* tpd word 1 bit 0:7 Custom Checksum task offload */ | ||
| 119 | #define TPD_PLOADOFFSET_MASK 0x00FF | ||
| 120 | #define TPD_PLOADOFFSET_SHIFT 0 | ||
| 121 | |||
| 122 | /* tpd word 1 bit 8:17 */ | ||
| 123 | #define TPD_CCSUM_EN_MASK 0x0001 | ||
| 124 | #define TPD_CCSUM_EN_SHIFT 8 | ||
| 125 | #define TPD_IP_CSUM_MASK 0x0001 | ||
| 126 | #define TPD_IP_CSUM_SHIFT 9 | ||
| 127 | #define TPD_TCP_CSUM_MASK 0x0001 | ||
| 128 | #define TPD_TCP_CSUM_SHIFT 10 | ||
| 129 | #define TPD_UDP_CSUM_MASK 0x0001 | ||
| 130 | #define TPD_UDP_CSUM_SHIFT 11 | ||
| 131 | #define TPD_LSO_EN_MASK 0x0001 /* TCP Large Send Offload */ | ||
| 132 | #define TPD_LSO_EN_SHIFT 12 | ||
| 133 | #define TPD_LSO_VER_MASK 0x0001 | ||
| 134 | #define TPD_LSO_VER_SHIFT 13 /* 0 : ipv4; 1 : ipv4/ipv6 */ | ||
| 135 | #define TPD_CON_VTAG_MASK 0x0001 | ||
| 136 | #define TPD_CON_VTAG_SHIFT 14 | ||
| 137 | #define TPD_INS_VTAG_MASK 0x0001 | ||
| 138 | #define TPD_INS_VTAG_SHIFT 15 | ||
| 139 | #define TPD_IPV4_PACKET_MASK 0x0001 /* valid when LSO VER is 1 */ | ||
| 140 | #define TPD_IPV4_PACKET_SHIFT 16 | ||
| 141 | #define TPD_ETH_TYPE_MASK 0x0001 | ||
| 142 | #define TPD_ETH_TYPE_SHIFT 17 /* 0 : 802.3 frame; 1 : Ethernet */ | ||
| 143 | |||
| 144 | /* tpd word 18:25 Custom Checksum task offload */ | ||
| 145 | #define TPD_CCSUM_OFFSET_MASK 0x00FF | ||
| 146 | #define TPD_CCSUM_OFFSET_SHIFT 18 | ||
| 147 | #define TPD_CCSUM_EPAD_MASK 0x0001 | ||
| 148 | #define TPD_CCSUM_EPAD_SHIFT 30 | ||
| 149 | |||
| 150 | /* tpd word 18:30 Large Send task offload (IPv4/IPV6) */ | ||
| 151 | #define TPD_MSS_MASK 0x1FFF | ||
| 152 | #define TPD_MSS_SHIFT 18 | ||
| 153 | |||
| 154 | #define TPD_EOP_MASK 0x0001 | ||
| 155 | #define TPD_EOP_SHIFT 31 | ||
| 156 | |||
| 157 | struct atl1c_tpd_desc { | ||
| 158 | __le16 buffer_len; /* include 4-byte CRC */ | ||
| 159 | __le16 vlan_tag; | ||
| 160 | __le32 word1; | ||
| 161 | __le64 buffer_addr; | ||
| 162 | }; | ||
| 163 | |||
| 164 | struct atl1c_tpd_ext_desc { | ||
| 165 | u32 reservd_0; | ||
| 166 | __le32 word1; | ||
| 167 | __le32 pkt_len; | ||
| 168 | u32 reservd_1; | ||
| 169 | }; | ||
| 170 | /* rrs word 0 bit 0:31 */ | ||
| 171 | #define RRS_RX_CSUM_MASK 0xFFFF | ||
| 172 | #define RRS_RX_CSUM_SHIFT 0 | ||
| 173 | #define RRS_RX_RFD_CNT_MASK 0x000F | ||
| 174 | #define RRS_RX_RFD_CNT_SHIFT 16 | ||
| 175 | #define RRS_RX_RFD_INDEX_MASK 0x0FFF | ||
| 176 | #define RRS_RX_RFD_INDEX_SHIFT 20 | ||
| 177 | |||
| 178 | /* rrs flag bit 0:16 */ | ||
| 179 | #define RRS_HEAD_LEN_MASK 0x00FF | ||
| 180 | #define RRS_HEAD_LEN_SHIFT 0 | ||
| 181 | #define RRS_HDS_TYPE_MASK 0x0003 | ||
| 182 | #define RRS_HDS_TYPE_SHIFT 8 | ||
| 183 | #define RRS_CPU_NUM_MASK 0x0003 | ||
| 184 | #define RRS_CPU_NUM_SHIFT 10 | ||
| 185 | #define RRS_HASH_FLG_MASK 0x000F | ||
| 186 | #define RRS_HASH_FLG_SHIFT 12 | ||
| 187 | |||
| 188 | #define RRS_HDS_TYPE_HEAD 1 | ||
| 189 | #define RRS_HDS_TYPE_DATA 2 | ||
| 190 | |||
| 191 | #define RRS_IS_NO_HDS_TYPE(flag) \ | ||
| 192 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0) | ||
| 193 | |||
| 194 | #define RRS_IS_HDS_HEAD(flag) \ | ||
| 195 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | ||
| 196 | RRS_HDS_TYPE_HEAD) | ||
| 197 | |||
| 198 | #define RRS_IS_HDS_DATA(flag) \ | ||
| 199 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | ||
| 200 | RRS_HDS_TYPE_DATA) | ||
| 201 | |||
| 202 | /* rrs word 3 bit 0:31 */ | ||
| 203 | #define RRS_PKT_SIZE_MASK 0x3FFF | ||
| 204 | #define RRS_PKT_SIZE_SHIFT 0 | ||
| 205 | #define RRS_ERR_L4_CSUM_MASK 0x0001 | ||
| 206 | #define RRS_ERR_L4_CSUM_SHIFT 14 | ||
| 207 | #define RRS_ERR_IP_CSUM_MASK 0x0001 | ||
| 208 | #define RRS_ERR_IP_CSUM_SHIFT 15 | ||
| 209 | #define RRS_VLAN_INS_MASK 0x0001 | ||
| 210 | #define RRS_VLAN_INS_SHIFT 16 | ||
| 211 | #define RRS_PROT_ID_MASK 0x0007 | ||
| 212 | #define RRS_PROT_ID_SHIFT 17 | ||
| 213 | #define RRS_RX_ERR_SUM_MASK 0x0001 | ||
| 214 | #define RRS_RX_ERR_SUM_SHIFT 20 | ||
| 215 | #define RRS_RX_ERR_CRC_MASK 0x0001 | ||
| 216 | #define RRS_RX_ERR_CRC_SHIFT 21 | ||
| 217 | #define RRS_RX_ERR_FAE_MASK 0x0001 | ||
| 218 | #define RRS_RX_ERR_FAE_SHIFT 22 | ||
| 219 | #define RRS_RX_ERR_TRUNC_MASK 0x0001 | ||
| 220 | #define RRS_RX_ERR_TRUNC_SHIFT 23 | ||
| 221 | #define RRS_RX_ERR_RUNC_MASK 0x0001 | ||
| 222 | #define RRS_RX_ERR_RUNC_SHIFT 24 | ||
| 223 | #define RRS_RX_ERR_ICMP_MASK 0x0001 | ||
| 224 | #define RRS_RX_ERR_ICMP_SHIFT 25 | ||
| 225 | #define RRS_PACKET_BCAST_MASK 0x0001 | ||
| 226 | #define RRS_PACKET_BCAST_SHIFT 26 | ||
| 227 | #define RRS_PACKET_MCAST_MASK 0x0001 | ||
| 228 | #define RRS_PACKET_MCAST_SHIFT 27 | ||
| 229 | #define RRS_PACKET_TYPE_MASK 0x0001 | ||
| 230 | #define RRS_PACKET_TYPE_SHIFT 28 | ||
| 231 | #define RRS_FIFO_FULL_MASK 0x0001 | ||
| 232 | #define RRS_FIFO_FULL_SHIFT 29 | ||
| 233 | #define RRS_802_3_LEN_ERR_MASK 0x0001 | ||
| 234 | #define RRS_802_3_LEN_ERR_SHIFT 30 | ||
| 235 | #define RRS_RXD_UPDATED_MASK 0x0001 | ||
| 236 | #define RRS_RXD_UPDATED_SHIFT 31 | ||
| 237 | |||
| 238 | #define RRS_ERR_L4_CSUM 0x00004000 | ||
| 239 | #define RRS_ERR_IP_CSUM 0x00008000 | ||
| 240 | #define RRS_VLAN_INS 0x00010000 | ||
| 241 | #define RRS_RX_ERR_SUM 0x00100000 | ||
| 242 | #define RRS_RX_ERR_CRC 0x00200000 | ||
| 243 | #define RRS_802_3_LEN_ERR 0x40000000 | ||
| 244 | #define RRS_RXD_UPDATED 0x80000000 | ||
| 245 | |||
| 246 | #define RRS_PACKET_TYPE_802_3 1 | ||
| 247 | #define RRS_PACKET_TYPE_ETH 0 | ||
| 248 | #define RRS_PACKET_IS_ETH(word) \ | ||
| 249 | (((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \ | ||
| 250 | RRS_PACKET_TYPE_ETH) | ||
| 251 | #define RRS_RXD_IS_VALID(word) \ | ||
| 252 | ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) | ||
| 253 | |||
| 254 | #define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \ | ||
| 255 | ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1) | ||
| 256 | #define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \ | ||
| 257 | ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6) | ||
| 258 | |||
| 259 | struct atl1c_recv_ret_status { | ||
| 260 | __le32 word0; | ||
| 261 | __le32 rss_hash; | ||
| 262 | __le16 vlan_tag; | ||
| 263 | __le16 flag; | ||
| 264 | __le32 word3; | ||
| 265 | }; | ||
| 266 | |||
| 267 | /* RFD desciptor */ | ||
| 268 | struct atl1c_rx_free_desc { | ||
| 269 | __le64 buffer_addr; | ||
| 270 | }; | ||
| 271 | |||
| 272 | /* DMA Order Settings */ | ||
| 273 | enum atl1c_dma_order { | ||
| 274 | atl1c_dma_ord_in = 1, | ||
| 275 | atl1c_dma_ord_enh = 2, | ||
| 276 | atl1c_dma_ord_out = 4 | ||
| 277 | }; | ||
| 278 | |||
| 279 | enum atl1c_dma_rcb { | ||
| 280 | atl1c_rcb_64 = 0, | ||
| 281 | atl1c_rcb_128 = 1 | ||
| 282 | }; | ||
| 283 | |||
| 284 | enum atl1c_mac_speed { | ||
| 285 | atl1c_mac_speed_0 = 0, | ||
| 286 | atl1c_mac_speed_10_100 = 1, | ||
| 287 | atl1c_mac_speed_1000 = 2 | ||
| 288 | }; | ||
| 289 | |||
| 290 | enum atl1c_dma_req_block { | ||
| 291 | atl1c_dma_req_128 = 0, | ||
| 292 | atl1c_dma_req_256 = 1, | ||
| 293 | atl1c_dma_req_512 = 2, | ||
| 294 | atl1c_dma_req_1024 = 3, | ||
| 295 | atl1c_dma_req_2048 = 4, | ||
| 296 | atl1c_dma_req_4096 = 5 | ||
| 297 | }; | ||
| 298 | |||
| 299 | enum atl1c_rss_mode { | ||
| 300 | atl1c_rss_mode_disable = 0, | ||
| 301 | atl1c_rss_sig_que = 1, | ||
| 302 | atl1c_rss_mul_que_sig_int = 2, | ||
| 303 | atl1c_rss_mul_que_mul_int = 4, | ||
| 304 | }; | ||
| 305 | |||
| 306 | enum atl1c_rss_type { | ||
| 307 | atl1c_rss_disable = 0, | ||
| 308 | atl1c_rss_ipv4 = 1, | ||
| 309 | atl1c_rss_ipv4_tcp = 2, | ||
| 310 | atl1c_rss_ipv6 = 4, | ||
| 311 | atl1c_rss_ipv6_tcp = 8 | ||
| 312 | }; | ||
| 313 | |||
| 314 | enum atl1c_nic_type { | ||
| 315 | athr_l1c = 0, | ||
| 316 | athr_l2c = 1, | ||
| 317 | }; | ||
| 318 | |||
| 319 | enum atl1c_trans_queue { | ||
| 320 | atl1c_trans_normal = 0, | ||
| 321 | atl1c_trans_high = 1 | ||
| 322 | }; | ||
| 323 | |||
| 324 | struct atl1c_hw_stats { | ||
| 325 | /* rx */ | ||
| 326 | unsigned long rx_ok; /* The number of good packet received. */ | ||
| 327 | unsigned long rx_bcast; /* The number of good broadcast packet received. */ | ||
| 328 | unsigned long rx_mcast; /* The number of good multicast packet received. */ | ||
| 329 | unsigned long rx_pause; /* The number of Pause packet received. */ | ||
| 330 | unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */ | ||
| 331 | unsigned long rx_fcs_err; /* The number of packets with bad FCS. */ | ||
| 332 | unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */ | ||
| 333 | unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */ | ||
| 334 | unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */ | ||
| 335 | unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */ | ||
| 336 | unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */ | ||
| 337 | unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */ | ||
| 338 | unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */ | ||
| 339 | unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */ | ||
| 340 | unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ | ||
| 341 | unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ | ||
| 342 | unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ | ||
| 343 | unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ | ||
| 344 | unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */ | ||
| 345 | unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */ | ||
| 346 | unsigned long rx_align_err; /* Alignment Error */ | ||
| 347 | unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ | ||
| 348 | unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ | ||
| 349 | unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */ | ||
| 350 | |||
| 351 | /* tx */ | ||
| 352 | unsigned long tx_ok; /* The number of good packet transmitted. */ | ||
| 353 | unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */ | ||
| 354 | unsigned long tx_mcast; /* The number of good multicast packet transmitted. */ | ||
| 355 | unsigned long tx_pause; /* The number of Pause packet transmitted. */ | ||
| 356 | unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */ | ||
| 357 | unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */ | ||
| 358 | unsigned long tx_defer; /* The number of packets transmitted that is deferred. */ | ||
| 359 | unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */ | ||
| 360 | unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */ | ||
| 361 | unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ | ||
| 362 | unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ | ||
| 363 | unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ | ||
| 364 | unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ | ||
| 365 | unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ | ||
| 366 | unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ | ||
| 367 | unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */ | ||
| 368 | unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ | ||
| 369 | unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */ | ||
| 370 | unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */ | ||
| 371 | unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ | ||
| 372 | unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ | ||
| 373 | unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */ | ||
| 374 | unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */ | ||
| 375 | unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */ | ||
| 376 | unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */ | ||
| 377 | }; | ||
| 378 | |||
| 379 | struct atl1c_hw { | ||
| 380 | u8 __iomem *hw_addr; /* inner register address */ | ||
| 381 | struct atl1c_adapter *adapter; | ||
| 382 | enum atl1c_nic_type nic_type; | ||
| 383 | enum atl1c_dma_order dma_order; | ||
| 384 | enum atl1c_dma_rcb rcb_value; | ||
| 385 | enum atl1c_dma_req_block dmar_block; | ||
| 386 | enum atl1c_dma_req_block dmaw_block; | ||
| 387 | |||
| 388 | u16 device_id; | ||
| 389 | u16 vendor_id; | ||
| 390 | u16 subsystem_id; | ||
| 391 | u16 subsystem_vendor_id; | ||
| 392 | u8 revision_id; | ||
| 393 | |||
| 394 | u32 intr_mask; | ||
| 395 | u8 dmaw_dly_cnt; | ||
| 396 | u8 dmar_dly_cnt; | ||
| 397 | |||
| 398 | u8 preamble_len; | ||
| 399 | u16 max_frame_size; | ||
| 400 | u16 min_frame_size; | ||
| 401 | |||
| 402 | enum atl1c_mac_speed mac_speed; | ||
| 403 | bool mac_duplex; | ||
| 404 | bool hibernate; | ||
| 405 | u16 media_type; | ||
| 406 | #define MEDIA_TYPE_AUTO_SENSOR 0 | ||
| 407 | #define MEDIA_TYPE_100M_FULL 1 | ||
| 408 | #define MEDIA_TYPE_100M_HALF 2 | ||
| 409 | #define MEDIA_TYPE_10M_FULL 3 | ||
| 410 | #define MEDIA_TYPE_10M_HALF 4 | ||
| 411 | |||
| 412 | u16 autoneg_advertised; | ||
| 413 | u16 mii_autoneg_adv_reg; | ||
| 414 | u16 mii_1000t_ctrl_reg; | ||
| 415 | |||
| 416 | u16 tx_imt; /* TX Interrupt Moderator timer ( 2us resolution) */ | ||
| 417 | u16 rx_imt; /* RX Interrupt Moderator timer ( 2us resolution) */ | ||
| 418 | u16 ict; /* Interrupt Clear timer (2us resolution) */ | ||
| 419 | u16 ctrl_flags; | ||
| 420 | #define ATL1C_INTR_CLEAR_ON_READ 0x0001 | ||
| 421 | #define ATL1C_INTR_MODRT_ENABLE 0x0002 | ||
| 422 | #define ATL1C_CMB_ENABLE 0x0004 | ||
| 423 | #define ATL1C_SMB_ENABLE 0x0010 | ||
| 424 | #define ATL1C_TXQ_MODE_ENHANCE 0x0020 | ||
| 425 | #define ATL1C_RX_IPV6_CHKSUM 0x0040 | ||
| 426 | #define ATL1C_ASPM_L0S_SUPPORT 0x0080 | ||
| 427 | #define ATL1C_ASPM_L1_SUPPORT 0x0100 | ||
| 428 | #define ATL1C_ASPM_CTRL_MON 0x0200 | ||
| 429 | #define ATL1C_HIB_DISABLE 0x0400 | ||
| 430 | #define ATL1C_LINK_CAP_1000M 0x0800 | ||
| 431 | #define ATL1C_FPGA_VERSION 0x8000 | ||
| 432 | u16 cmb_tpd; | ||
| 433 | u16 cmb_rrd; | ||
| 434 | u16 cmb_rx_timer; /* 2us resolution */ | ||
| 435 | u16 cmb_tx_timer; | ||
| 436 | u32 smb_timer; | ||
| 437 | |||
| 438 | u16 rrd_thresh; /* Threshold of number of RRD produced to trigger | ||
| 439 | interrupt request */ | ||
| 440 | u16 tpd_thresh; | ||
| 441 | u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ | ||
| 442 | u8 rfd_burst; | ||
| 443 | enum atl1c_rss_type rss_type; | ||
| 444 | enum atl1c_rss_mode rss_mode; | ||
| 445 | u8 rss_hash_bits; | ||
| 446 | u32 base_cpu; | ||
| 447 | u32 indirect_tab; | ||
| 448 | u8 mac_addr[ETH_ALEN]; | ||
| 449 | u8 perm_mac_addr[ETH_ALEN]; | ||
| 450 | |||
| 451 | bool phy_configured; | ||
| 452 | bool re_autoneg; | ||
| 453 | bool emi_ca; | ||
| 454 | }; | ||
| 455 | |||
| 456 | /* | ||
| 457 | * atl1c_ring_header represents a single, contiguous block of DMA space | ||
| 458 | * mapped for the three descriptor rings (tpd, rfd, rrd) and the two | ||
| 459 | * message blocks (cmb, smb) described below | ||
| 460 | */ | ||
| 461 | struct atl1c_ring_header { | ||
| 462 | void *desc; /* virtual address */ | ||
| 463 | dma_addr_t dma; /* physical address*/ | ||
| 464 | unsigned int size; /* length in bytes */ | ||
| 465 | }; | ||
| 466 | |||
| 467 | /* | ||
| 468 | * atl1c_buffer is wrapper around a pointer to a socket buffer | ||
| 469 | * so a DMA handle can be stored along with the skb | ||
| 470 | */ | ||
| 471 | struct atl1c_buffer { | ||
| 472 | struct sk_buff *skb; /* socket buffer */ | ||
| 473 | u16 length; /* rx buffer length */ | ||
| 474 | u16 state; /* state of buffer */ | ||
| 475 | #define ATL1_BUFFER_FREE 0 | ||
| 476 | #define ATL1_BUFFER_BUSY 1 | ||
| 477 | dma_addr_t dma; | ||
| 478 | }; | ||
| 479 | |||
| 480 | /* transimit packet descriptor (tpd) ring */ | ||
| 481 | struct atl1c_tpd_ring { | ||
| 482 | void *desc; /* descriptor ring virtual address */ | ||
| 483 | dma_addr_t dma; /* descriptor ring physical address */ | ||
| 484 | u16 size; /* descriptor ring length in bytes */ | ||
| 485 | u16 count; /* number of descriptors in the ring */ | ||
| 486 | u16 next_to_use; /* this is protectd by adapter->tx_lock */ | ||
| 487 | atomic_t next_to_clean; | ||
| 488 | struct atl1c_buffer *buffer_info; | ||
| 489 | }; | ||
| 490 | |||
| 491 | /* receive free descriptor (rfd) ring */ | ||
| 492 | struct atl1c_rfd_ring { | ||
| 493 | void *desc; /* descriptor ring virtual address */ | ||
| 494 | dma_addr_t dma; /* descriptor ring physical address */ | ||
| 495 | u16 size; /* descriptor ring length in bytes */ | ||
| 496 | u16 count; /* number of descriptors in the ring */ | ||
| 497 | u16 next_to_use; | ||
| 498 | u16 next_to_clean; | ||
| 499 | struct atl1c_buffer *buffer_info; | ||
| 500 | }; | ||
| 501 | |||
| 502 | /* receive return desciptor (rrd) ring */ | ||
| 503 | struct atl1c_rrd_ring { | ||
| 504 | void *desc; /* descriptor ring virtual address */ | ||
| 505 | dma_addr_t dma; /* descriptor ring physical address */ | ||
| 506 | u16 size; /* descriptor ring length in bytes */ | ||
| 507 | u16 count; /* number of descriptors in the ring */ | ||
| 508 | u16 next_to_use; | ||
| 509 | u16 next_to_clean; | ||
| 510 | }; | ||
| 511 | |||
| 512 | struct atl1c_cmb { | ||
| 513 | void *cmb; | ||
| 514 | dma_addr_t dma; | ||
| 515 | }; | ||
| 516 | |||
| 517 | struct atl1c_smb { | ||
| 518 | void *smb; | ||
| 519 | dma_addr_t dma; | ||
| 520 | }; | ||
| 521 | |||
| 522 | /* board specific private data structure */ | ||
| 523 | struct atl1c_adapter { | ||
| 524 | struct net_device *netdev; | ||
| 525 | struct pci_dev *pdev; | ||
| 526 | struct vlan_group *vlgrp; | ||
| 527 | struct napi_struct napi; | ||
| 528 | struct atl1c_hw hw; | ||
| 529 | struct atl1c_hw_stats hw_stats; | ||
| 530 | struct net_device_stats net_stats; | ||
| 531 | struct mii_if_info mii; /* MII interface info */ | ||
| 532 | u16 rx_buffer_len; | ||
| 533 | |||
| 534 | unsigned long flags; | ||
| 535 | #define __AT_TESTING 0x0001 | ||
| 536 | #define __AT_RESETTING 0x0002 | ||
| 537 | #define __AT_DOWN 0x0003 | ||
| 538 | u32 msg_enable; | ||
| 539 | |||
| 540 | bool have_msi; | ||
| 541 | u32 wol; | ||
| 542 | u16 link_speed; | ||
| 543 | u16 link_duplex; | ||
| 544 | |||
| 545 | spinlock_t mdio_lock; | ||
| 546 | spinlock_t tx_lock; | ||
| 547 | atomic_t irq_sem; | ||
| 548 | |||
| 549 | struct work_struct reset_task; | ||
| 550 | struct work_struct link_chg_task; | ||
| 551 | struct timer_list watchdog_timer; | ||
| 552 | struct timer_list phy_config_timer; | ||
| 553 | |||
| 554 | /* All Descriptor memory */ | ||
| 555 | struct atl1c_ring_header ring_header; | ||
| 556 | struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; | ||
| 557 | struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE]; | ||
| 558 | struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE]; | ||
| 559 | struct atl1c_cmb cmb; | ||
| 560 | struct atl1c_smb smb; | ||
| 561 | int num_rx_queues; | ||
| 562 | u32 bd_number; /* board number;*/ | ||
| 563 | }; | ||
| 564 | |||
| 565 | #define AT_WRITE_REG(a, reg, value) ( \ | ||
| 566 | writel((value), ((a)->hw_addr + reg))) | ||
| 567 | |||
| 568 | #define AT_WRITE_FLUSH(a) (\ | ||
| 569 | readl((a)->hw_addr)) | ||
| 570 | |||
| 571 | #define AT_READ_REG(a, reg, pdata) do { \ | ||
| 572 | if (unlikely((a)->hibernate)) { \ | ||
| 573 | readl((a)->hw_addr + reg); \ | ||
| 574 | *(u32 *)pdata = readl((a)->hw_addr + reg); \ | ||
| 575 | } else { \ | ||
| 576 | *(u32 *)pdata = readl((a)->hw_addr + reg); \ | ||
| 577 | } \ | ||
| 578 | } while (0) | ||
| 579 | |||
| 580 | #define AT_WRITE_REGB(a, reg, value) (\ | ||
| 581 | writeb((value), ((a)->hw_addr + reg))) | ||
| 582 | |||
| 583 | #define AT_READ_REGB(a, reg) (\ | ||
| 584 | readb((a)->hw_addr + reg)) | ||
| 585 | |||
| 586 | #define AT_WRITE_REGW(a, reg, value) (\ | ||
| 587 | writew((value), ((a)->hw_addr + reg))) | ||
| 588 | |||
| 589 | #define AT_READ_REGW(a, reg) (\ | ||
| 590 | readw((a)->hw_addr + reg)) | ||
| 591 | |||
| 592 | #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ | ||
| 593 | writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) | ||
| 594 | |||
| 595 | #define AT_READ_REG_ARRAY(a, reg, offset) ( \ | ||
| 596 | readl(((a)->hw_addr + reg) + ((offset) << 2))) | ||
| 597 | |||
| 598 | extern char atl1c_driver_name[]; | ||
| 599 | extern char atl1c_driver_version[]; | ||
| 600 | |||
| 601 | extern int atl1c_up(struct atl1c_adapter *adapter); | ||
| 602 | extern void atl1c_down(struct atl1c_adapter *adapter); | ||
| 603 | extern void atl1c_reinit_locked(struct atl1c_adapter *adapter); | ||
| 604 | extern s32 atl1c_reset_hw(struct atl1c_hw *hw); | ||
| 605 | extern void atl1c_set_ethtool_ops(struct net_device *netdev); | ||
| 606 | #endif /* _ATL1C_H_ */ | ||
diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c new file mode 100644 index 00000000000..45c5b7332cd --- /dev/null +++ b/drivers/net/atl1c/atl1c_ethtool.c | |||
| @@ -0,0 +1,317 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Derived from Intel e1000 driver | ||
| 5 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/netdevice.h> | ||
| 24 | #include <linux/ethtool.h> | ||
| 25 | |||
| 26 | #include "atl1c.h" | ||
| 27 | |||
| 28 | static int atl1c_get_settings(struct net_device *netdev, | ||
| 29 | struct ethtool_cmd *ecmd) | ||
| 30 | { | ||
| 31 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 32 | struct atl1c_hw *hw = &adapter->hw; | ||
| 33 | |||
| 34 | ecmd->supported = (SUPPORTED_10baseT_Half | | ||
| 35 | SUPPORTED_10baseT_Full | | ||
| 36 | SUPPORTED_100baseT_Half | | ||
| 37 | SUPPORTED_100baseT_Full | | ||
| 38 | SUPPORTED_Autoneg | | ||
| 39 | SUPPORTED_TP); | ||
| 40 | if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) | ||
| 41 | ecmd->supported |= SUPPORTED_1000baseT_Full; | ||
| 42 | |||
| 43 | ecmd->advertising = ADVERTISED_TP; | ||
| 44 | |||
| 45 | ecmd->advertising |= hw->autoneg_advertised; | ||
| 46 | |||
| 47 | ecmd->port = PORT_TP; | ||
| 48 | ecmd->phy_address = 0; | ||
| 49 | ecmd->transceiver = XCVR_INTERNAL; | ||
| 50 | |||
| 51 | if (adapter->link_speed != SPEED_0) { | ||
| 52 | ecmd->speed = adapter->link_speed; | ||
| 53 | if (adapter->link_duplex == FULL_DUPLEX) | ||
| 54 | ecmd->duplex = DUPLEX_FULL; | ||
| 55 | else | ||
| 56 | ecmd->duplex = DUPLEX_HALF; | ||
| 57 | } else { | ||
| 58 | ecmd->speed = -1; | ||
| 59 | ecmd->duplex = -1; | ||
| 60 | } | ||
| 61 | |||
| 62 | ecmd->autoneg = AUTONEG_ENABLE; | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int atl1c_set_settings(struct net_device *netdev, | ||
| 67 | struct ethtool_cmd *ecmd) | ||
| 68 | { | ||
| 69 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 70 | struct atl1c_hw *hw = &adapter->hw; | ||
| 71 | u16 autoneg_advertised; | ||
| 72 | |||
| 73 | while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) | ||
| 74 | msleep(1); | ||
| 75 | |||
| 76 | if (ecmd->autoneg == AUTONEG_ENABLE) { | ||
| 77 | autoneg_advertised = ADVERTISED_Autoneg; | ||
| 78 | } else { | ||
| 79 | if (ecmd->speed == SPEED_1000) { | ||
| 80 | if (ecmd->duplex != DUPLEX_FULL) { | ||
| 81 | if (netif_msg_link(adapter)) | ||
| 82 | dev_warn(&adapter->pdev->dev, | ||
| 83 | "1000M half is invalid\n"); | ||
| 84 | clear_bit(__AT_RESETTING, &adapter->flags); | ||
| 85 | return -EINVAL; | ||
| 86 | } | ||
| 87 | autoneg_advertised = ADVERTISED_1000baseT_Full; | ||
| 88 | } else if (ecmd->speed == SPEED_100) { | ||
| 89 | if (ecmd->duplex == DUPLEX_FULL) | ||
| 90 | autoneg_advertised = ADVERTISED_100baseT_Full; | ||
| 91 | else | ||
| 92 | autoneg_advertised = ADVERTISED_100baseT_Half; | ||
| 93 | } else { | ||
| 94 | if (ecmd->duplex == DUPLEX_FULL) | ||
| 95 | autoneg_advertised = ADVERTISED_10baseT_Full; | ||
| 96 | else | ||
| 97 | autoneg_advertised = ADVERTISED_10baseT_Half; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | if (hw->autoneg_advertised != autoneg_advertised) { | ||
| 102 | hw->autoneg_advertised = autoneg_advertised; | ||
| 103 | if (atl1c_restart_autoneg(hw) != 0) { | ||
| 104 | if (netif_msg_link(adapter)) | ||
| 105 | dev_warn(&adapter->pdev->dev, | ||
| 106 | "ethtool speed/duplex setting failed\n"); | ||
| 107 | clear_bit(__AT_RESETTING, &adapter->flags); | ||
| 108 | return -EINVAL; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | clear_bit(__AT_RESETTING, &adapter->flags); | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static u32 atl1c_get_tx_csum(struct net_device *netdev) | ||
| 116 | { | ||
| 117 | return (netdev->features & NETIF_F_HW_CSUM) != 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static u32 atl1c_get_msglevel(struct net_device *netdev) | ||
| 121 | { | ||
| 122 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 123 | return adapter->msg_enable; | ||
| 124 | } | ||
| 125 | |||
| 126 | static void atl1c_set_msglevel(struct net_device *netdev, u32 data) | ||
| 127 | { | ||
| 128 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 129 | adapter->msg_enable = data; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int atl1c_get_regs_len(struct net_device *netdev) | ||
| 133 | { | ||
| 134 | return AT_REGS_LEN; | ||
| 135 | } | ||
| 136 | |||
| 137 | static void atl1c_get_regs(struct net_device *netdev, | ||
| 138 | struct ethtool_regs *regs, void *p) | ||
| 139 | { | ||
| 140 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 141 | struct atl1c_hw *hw = &adapter->hw; | ||
| 142 | u32 *regs_buff = p; | ||
| 143 | u16 phy_data; | ||
| 144 | |||
| 145 | memset(p, 0, AT_REGS_LEN); | ||
| 146 | |||
| 147 | regs->version = 0; | ||
| 148 | AT_READ_REG(hw, REG_VPD_CAP, p++); | ||
| 149 | AT_READ_REG(hw, REG_PM_CTRL, p++); | ||
| 150 | AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); | ||
| 151 | AT_READ_REG(hw, REG_TWSI_CTRL, p++); | ||
| 152 | AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL, p++); | ||
| 153 | AT_READ_REG(hw, REG_MASTER_CTRL, p++); | ||
| 154 | AT_READ_REG(hw, REG_MANUAL_TIMER_INIT, p++); | ||
| 155 | AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++); | ||
| 156 | AT_READ_REG(hw, REG_GPHY_CTRL, p++); | ||
| 157 | AT_READ_REG(hw, REG_LINK_CTRL, p++); | ||
| 158 | AT_READ_REG(hw, REG_IDLE_STATUS, p++); | ||
| 159 | AT_READ_REG(hw, REG_MDIO_CTRL, p++); | ||
| 160 | AT_READ_REG(hw, REG_SERDES_LOCK, p++); | ||
| 161 | AT_READ_REG(hw, REG_MAC_CTRL, p++); | ||
| 162 | AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); | ||
| 163 | AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); | ||
| 164 | AT_READ_REG(hw, REG_MAC_STA_ADDR+4, p++); | ||
| 165 | AT_READ_REG(hw, REG_RX_HASH_TABLE, p++); | ||
| 166 | AT_READ_REG(hw, REG_RX_HASH_TABLE+4, p++); | ||
| 167 | AT_READ_REG(hw, REG_RXQ_CTRL, p++); | ||
| 168 | AT_READ_REG(hw, REG_TXQ_CTRL, p++); | ||
| 169 | AT_READ_REG(hw, REG_MTU, p++); | ||
| 170 | AT_READ_REG(hw, REG_WOL_CTRL, p++); | ||
| 171 | |||
| 172 | atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); | ||
| 173 | regs_buff[73] = (u32) phy_data; | ||
| 174 | atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||
| 175 | regs_buff[74] = (u32) phy_data; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int atl1c_get_eeprom_len(struct net_device *netdev) | ||
| 179 | { | ||
| 180 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 181 | |||
| 182 | if (atl1c_check_eeprom_exist(&adapter->hw)) | ||
| 183 | return AT_EEPROM_LEN; | ||
| 184 | else | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int atl1c_get_eeprom(struct net_device *netdev, | ||
| 189 | struct ethtool_eeprom *eeprom, u8 *bytes) | ||
| 190 | { | ||
| 191 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 192 | struct atl1c_hw *hw = &adapter->hw; | ||
| 193 | u32 *eeprom_buff; | ||
| 194 | int first_dword, last_dword; | ||
| 195 | int ret_val = 0; | ||
| 196 | int i; | ||
| 197 | |||
| 198 | if (eeprom->len == 0) | ||
| 199 | return -EINVAL; | ||
| 200 | |||
| 201 | if (!atl1c_check_eeprom_exist(hw)) /* not exist */ | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | eeprom->magic = adapter->pdev->vendor | | ||
| 205 | (adapter->pdev->device << 16); | ||
| 206 | |||
| 207 | first_dword = eeprom->offset >> 2; | ||
| 208 | last_dword = (eeprom->offset + eeprom->len - 1) >> 2; | ||
| 209 | |||
| 210 | eeprom_buff = kmalloc(sizeof(u32) * | ||
| 211 | (last_dword - first_dword + 1), GFP_KERNEL); | ||
| 212 | if (eeprom_buff == NULL) | ||
| 213 | return -ENOMEM; | ||
| 214 | |||
| 215 | for (i = first_dword; i < last_dword; i++) { | ||
| 216 | if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { | ||
| 217 | kfree(eeprom_buff); | ||
| 218 | return -EIO; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), | ||
| 223 | eeprom->len); | ||
| 224 | kfree(eeprom_buff); | ||
| 225 | |||
| 226 | return ret_val; | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static void atl1c_get_drvinfo(struct net_device *netdev, | ||
| 231 | struct ethtool_drvinfo *drvinfo) | ||
| 232 | { | ||
| 233 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 234 | |||
| 235 | strncpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver)); | ||
| 236 | strncpy(drvinfo->version, atl1c_driver_version, | ||
| 237 | sizeof(drvinfo->version)); | ||
| 238 | strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); | ||
| 239 | strncpy(drvinfo->bus_info, pci_name(adapter->pdev), | ||
| 240 | sizeof(drvinfo->bus_info)); | ||
| 241 | drvinfo->n_stats = 0; | ||
| 242 | drvinfo->testinfo_len = 0; | ||
| 243 | drvinfo->regdump_len = atl1c_get_regs_len(netdev); | ||
| 244 | drvinfo->eedump_len = atl1c_get_eeprom_len(netdev); | ||
| 245 | } | ||
| 246 | |||
| 247 | static void atl1c_get_wol(struct net_device *netdev, | ||
| 248 | struct ethtool_wolinfo *wol) | ||
| 249 | { | ||
| 250 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 251 | |||
| 252 | wol->supported = WAKE_MAGIC | WAKE_PHY; | ||
| 253 | wol->wolopts = 0; | ||
| 254 | |||
| 255 | if (adapter->wol & AT_WUFC_EX) | ||
| 256 | wol->wolopts |= WAKE_UCAST; | ||
| 257 | if (adapter->wol & AT_WUFC_MC) | ||
| 258 | wol->wolopts |= WAKE_MCAST; | ||
| 259 | if (adapter->wol & AT_WUFC_BC) | ||
| 260 | wol->wolopts |= WAKE_BCAST; | ||
| 261 | if (adapter->wol & AT_WUFC_MAG) | ||
| 262 | wol->wolopts |= WAKE_MAGIC; | ||
| 263 | if (adapter->wol & AT_WUFC_LNKC) | ||
| 264 | wol->wolopts |= WAKE_PHY; | ||
| 265 | |||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 269 | static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
| 270 | { | ||
| 271 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 272 | |||
| 273 | if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | | ||
| 274 | WAKE_MCAST | WAKE_BCAST | WAKE_MCAST)) | ||
| 275 | return -EOPNOTSUPP; | ||
| 276 | /* these settings will always override what we currently have */ | ||
| 277 | adapter->wol = 0; | ||
| 278 | |||
| 279 | if (wol->wolopts & WAKE_MAGIC) | ||
| 280 | adapter->wol |= AT_WUFC_MAG; | ||
| 281 | if (wol->wolopts & WAKE_PHY) | ||
| 282 | adapter->wol |= AT_WUFC_LNKC; | ||
| 283 | |||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | static int atl1c_nway_reset(struct net_device *netdev) | ||
| 288 | { | ||
| 289 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 290 | if (netif_running(netdev)) | ||
| 291 | atl1c_reinit_locked(adapter); | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | |||
| 295 | static struct ethtool_ops atl1c_ethtool_ops = { | ||
| 296 | .get_settings = atl1c_get_settings, | ||
| 297 | .set_settings = atl1c_set_settings, | ||
| 298 | .get_drvinfo = atl1c_get_drvinfo, | ||
| 299 | .get_regs_len = atl1c_get_regs_len, | ||
| 300 | .get_regs = atl1c_get_regs, | ||
| 301 | .get_wol = atl1c_get_wol, | ||
| 302 | .set_wol = atl1c_set_wol, | ||
| 303 | .get_msglevel = atl1c_get_msglevel, | ||
| 304 | .set_msglevel = atl1c_set_msglevel, | ||
| 305 | .nway_reset = atl1c_nway_reset, | ||
| 306 | .get_link = ethtool_op_get_link, | ||
| 307 | .get_eeprom_len = atl1c_get_eeprom_len, | ||
| 308 | .get_eeprom = atl1c_get_eeprom, | ||
| 309 | .get_tx_csum = atl1c_get_tx_csum, | ||
| 310 | .get_sg = ethtool_op_get_sg, | ||
| 311 | .set_sg = ethtool_op_set_sg, | ||
| 312 | }; | ||
| 313 | |||
| 314 | void atl1c_set_ethtool_ops(struct net_device *netdev) | ||
| 315 | { | ||
| 316 | SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops); | ||
| 317 | } | ||
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c new file mode 100644 index 00000000000..3e69b940b8f --- /dev/null +++ b/drivers/net/atl1c/atl1c_hw.c | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Derived from Intel e1000 driver | ||
| 5 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | ||
| 21 | #include <linux/pci.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/mii.h> | ||
| 24 | #include <linux/crc32.h> | ||
| 25 | |||
| 26 | #include "atl1c.h" | ||
| 27 | |||
| 28 | /* | ||
| 29 | * check_eeprom_exist | ||
| 30 | * return 1 if eeprom exist | ||
| 31 | */ | ||
| 32 | int atl1c_check_eeprom_exist(struct atl1c_hw *hw) | ||
| 33 | { | ||
| 34 | u32 data; | ||
| 35 | |||
| 36 | AT_READ_REG(hw, REG_TWSI_DEBUG, &data); | ||
| 37 | if (data & TWSI_DEBUG_DEV_EXIST) | ||
| 38 | return 1; | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) | ||
| 44 | { | ||
| 45 | u32 value; | ||
| 46 | /* | ||
| 47 | * 00-0B-6A-F6-00-DC | ||
| 48 | * 0: 6AF600DC 1: 000B | ||
| 49 | * low dword | ||
| 50 | */ | ||
| 51 | value = (((u32)hw->mac_addr[2]) << 24) | | ||
| 52 | (((u32)hw->mac_addr[3]) << 16) | | ||
| 53 | (((u32)hw->mac_addr[4]) << 8) | | ||
| 54 | (((u32)hw->mac_addr[5])) ; | ||
| 55 | AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); | ||
| 56 | /* hight dword */ | ||
| 57 | value = (((u32)hw->mac_addr[0]) << 8) | | ||
| 58 | (((u32)hw->mac_addr[1])) ; | ||
| 59 | AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* | ||
| 63 | * atl1c_get_permanent_address | ||
| 64 | * return 0 if get valid mac address, | ||
| 65 | */ | ||
| 66 | static int atl1c_get_permanent_address(struct atl1c_hw *hw) | ||
| 67 | { | ||
| 68 | u32 addr[2]; | ||
| 69 | u32 i; | ||
| 70 | u32 otp_ctrl_data; | ||
| 71 | u32 twsi_ctrl_data; | ||
| 72 | u8 eth_addr[ETH_ALEN]; | ||
| 73 | |||
| 74 | /* init */ | ||
| 75 | addr[0] = addr[1] = 0; | ||
| 76 | AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); | ||
| 77 | if (atl1c_check_eeprom_exist(hw)) { | ||
| 78 | /* Enable OTP CLK */ | ||
| 79 | if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { | ||
| 80 | otp_ctrl_data |= OTP_CTRL_CLK_EN; | ||
| 81 | AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||
| 82 | AT_WRITE_FLUSH(hw); | ||
| 83 | msleep(1); | ||
| 84 | } | ||
| 85 | |||
| 86 | AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); | ||
| 87 | twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; | ||
| 88 | AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); | ||
| 89 | for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { | ||
| 90 | msleep(10); | ||
| 91 | AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); | ||
| 92 | if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | if (i >= AT_TWSI_EEPROM_TIMEOUT) | ||
| 96 | return -1; | ||
| 97 | } | ||
| 98 | /* Disable OTP_CLK */ | ||
| 99 | if (otp_ctrl_data & OTP_CTRL_CLK_EN) { | ||
| 100 | otp_ctrl_data &= ~OTP_CTRL_CLK_EN; | ||
| 101 | AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||
| 102 | AT_WRITE_FLUSH(hw); | ||
| 103 | msleep(1); | ||
| 104 | } | ||
| 105 | |||
| 106 | /* maybe MAC-address is from BIOS */ | ||
| 107 | AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); | ||
| 108 | AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); | ||
| 109 | *(u32 *) ð_addr[2] = swab32(addr[0]); | ||
| 110 | *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); | ||
| 111 | |||
| 112 | if (is_valid_ether_addr(eth_addr)) { | ||
| 113 | memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | return -1; | ||
| 118 | } | ||
| 119 | |||
| 120 | bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value) | ||
| 121 | { | ||
| 122 | int i; | ||
| 123 | int ret = false; | ||
| 124 | u32 otp_ctrl_data; | ||
| 125 | u32 control; | ||
| 126 | u32 data; | ||
| 127 | |||
| 128 | if (offset & 3) | ||
| 129 | return ret; /* address do not align */ | ||
| 130 | |||
| 131 | AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); | ||
| 132 | if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) | ||
| 133 | AT_WRITE_REG(hw, REG_OTP_CTRL, | ||
| 134 | (otp_ctrl_data | OTP_CTRL_CLK_EN)); | ||
| 135 | |||
| 136 | AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0); | ||
| 137 | control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT; | ||
| 138 | AT_WRITE_REG(hw, REG_EEPROM_CTRL, control); | ||
| 139 | |||
| 140 | for (i = 0; i < 10; i++) { | ||
| 141 | udelay(100); | ||
| 142 | AT_READ_REG(hw, REG_EEPROM_CTRL, &control); | ||
| 143 | if (control & EEPROM_CTRL_RW) | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | if (control & EEPROM_CTRL_RW) { | ||
| 147 | AT_READ_REG(hw, REG_EEPROM_CTRL, &data); | ||
| 148 | AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value); | ||
| 149 | data = data & 0xFFFF; | ||
| 150 | *p_value = swab32((data << 16) | (*p_value >> 16)); | ||
| 151 | ret = true; | ||
| 152 | } | ||
| 153 | if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) | ||
| 154 | AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||
| 155 | |||
| 156 | return ret; | ||
| 157 | } | ||
| 158 | /* | ||
| 159 | * Reads the adapter's MAC address from the EEPROM | ||
| 160 | * | ||
| 161 | * hw - Struct containing variables accessed by shared code | ||
| 162 | */ | ||
| 163 | int atl1c_read_mac_addr(struct atl1c_hw *hw) | ||
| 164 | { | ||
| 165 | int err = 0; | ||
| 166 | |||
| 167 | err = atl1c_get_permanent_address(hw); | ||
| 168 | if (err) | ||
| 169 | random_ether_addr(hw->perm_mac_addr); | ||
| 170 | |||
| 171 | memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* | ||
| 176 | * atl1c_hash_mc_addr | ||
| 177 | * purpose | ||
| 178 | * set hash value for a multicast address | ||
| 179 | * hash calcu processing : | ||
| 180 | * 1. calcu 32bit CRC for multicast address | ||
| 181 | * 2. reverse crc with MSB to LSB | ||
| 182 | */ | ||
| 183 | u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr) | ||
| 184 | { | ||
| 185 | u32 crc32; | ||
| 186 | u32 value = 0; | ||
| 187 | int i; | ||
| 188 | |||
| 189 | crc32 = ether_crc_le(6, mc_addr); | ||
| 190 | for (i = 0; i < 32; i++) | ||
| 191 | value |= (((crc32 >> i) & 1) << (31 - i)); | ||
| 192 | |||
| 193 | return value; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 197 | * Sets the bit in the multicast table corresponding to the hash value. | ||
| 198 | * hw - Struct containing variables accessed by shared code | ||
| 199 | * hash_value - Multicast address hash value | ||
| 200 | */ | ||
| 201 | void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) | ||
| 202 | { | ||
| 203 | u32 hash_bit, hash_reg; | ||
| 204 | u32 mta; | ||
| 205 | |||
| 206 | /* | ||
| 207 | * The HASH Table is a register array of 2 32-bit registers. | ||
| 208 | * It is treated like an array of 64 bits. We want to set | ||
| 209 | * bit BitArray[hash_value]. So we figure out what register | ||
| 210 | * the bit is in, read it, OR in the new bit, then write | ||
| 211 | * back the new value. The register is determined by the | ||
| 212 | * upper bit of the hash value and the bit within that | ||
| 213 | * register are determined by the lower 5 bits of the value. | ||
| 214 | */ | ||
| 215 | hash_reg = (hash_value >> 31) & 0x1; | ||
| 216 | hash_bit = (hash_value >> 26) & 0x1F; | ||
| 217 | |||
| 218 | mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); | ||
| 219 | |||
| 220 | mta |= (1 << hash_bit); | ||
| 221 | |||
| 222 | AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Reads the value from a PHY register | ||
| 227 | * hw - Struct containing variables accessed by shared code | ||
| 228 | * reg_addr - address of the PHY register to read | ||
| 229 | */ | ||
| 230 | int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) | ||
| 231 | { | ||
| 232 | u32 val; | ||
| 233 | int i; | ||
| 234 | |||
| 235 | val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | | ||
| 236 | MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | | ||
| 237 | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; | ||
| 238 | |||
| 239 | AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||
| 240 | |||
| 241 | for (i = 0; i < MDIO_WAIT_TIMES; i++) { | ||
| 242 | udelay(2); | ||
| 243 | AT_READ_REG(hw, REG_MDIO_CTRL, &val); | ||
| 244 | if (!(val & (MDIO_START | MDIO_BUSY))) | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | if (!(val & (MDIO_START | MDIO_BUSY))) { | ||
| 248 | *phy_data = (u16)val; | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | return -1; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | * Writes a value to a PHY register | ||
| 257 | * hw - Struct containing variables accessed by shared code | ||
| 258 | * reg_addr - address of the PHY register to write | ||
| 259 | * data - data to write to the PHY | ||
| 260 | */ | ||
| 261 | int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) | ||
| 262 | { | ||
| 263 | int i; | ||
| 264 | u32 val; | ||
| 265 | |||
| 266 | val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | | ||
| 267 | (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | | ||
| 268 | MDIO_SUP_PREAMBLE | MDIO_START | | ||
| 269 | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; | ||
| 270 | |||
| 271 | AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||
| 272 | |||
| 273 | for (i = 0; i < MDIO_WAIT_TIMES; i++) { | ||
| 274 | udelay(2); | ||
| 275 | AT_READ_REG(hw, REG_MDIO_CTRL, &val); | ||
| 276 | if (!(val & (MDIO_START | MDIO_BUSY))) | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | if (!(val & (MDIO_START | MDIO_BUSY))) | ||
| 281 | return 0; | ||
| 282 | |||
| 283 | return -1; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* | ||
| 287 | * Configures PHY autoneg and flow control advertisement settings | ||
| 288 | * | ||
| 289 | * hw - Struct containing variables accessed by shared code | ||
| 290 | */ | ||
| 291 | static int atl1c_phy_setup_adv(struct atl1c_hw *hw) | ||
| 292 | { | ||
| 293 | u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK; | ||
| 294 | u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP & | ||
| 295 | ~GIGA_CR_1000T_SPEED_MASK; | ||
| 296 | |||
| 297 | if (hw->autoneg_advertised & ADVERTISED_10baseT_Half) | ||
| 298 | mii_adv_data |= ADVERTISE_10HALF; | ||
| 299 | if (hw->autoneg_advertised & ADVERTISED_10baseT_Full) | ||
| 300 | mii_adv_data |= ADVERTISE_10FULL; | ||
| 301 | if (hw->autoneg_advertised & ADVERTISED_100baseT_Half) | ||
| 302 | mii_adv_data |= ADVERTISE_100HALF; | ||
| 303 | if (hw->autoneg_advertised & ADVERTISED_100baseT_Full) | ||
| 304 | mii_adv_data |= ADVERTISE_100FULL; | ||
| 305 | |||
| 306 | if (hw->autoneg_advertised & ADVERTISED_Autoneg) | ||
| 307 | mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL | | ||
| 308 | ADVERTISE_100HALF | ADVERTISE_100FULL; | ||
| 309 | |||
| 310 | if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) { | ||
| 311 | if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half) | ||
| 312 | mii_giga_ctrl_data |= ADVERTISE_1000HALF; | ||
| 313 | if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full) | ||
| 314 | mii_giga_ctrl_data |= ADVERTISE_1000FULL; | ||
| 315 | if (hw->autoneg_advertised & ADVERTISED_Autoneg) | ||
| 316 | mii_giga_ctrl_data |= ADVERTISE_1000HALF | | ||
| 317 | ADVERTISE_1000FULL; | ||
| 318 | } | ||
| 319 | |||
| 320 | if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 || | ||
| 321 | atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0) | ||
| 322 | return -1; | ||
| 323 | return 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | void atl1c_phy_disable(struct atl1c_hw *hw) | ||
| 327 | { | ||
| 328 | AT_WRITE_REGW(hw, REG_GPHY_CTRL, | ||
| 329 | GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); | ||
| 330 | } | ||
| 331 | |||
| 332 | static void atl1c_phy_magic_data(struct atl1c_hw *hw) | ||
| 333 | { | ||
| 334 | u16 data; | ||
| 335 | |||
| 336 | data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE | | ||
| 337 | ((1 & ANA_INTERVAL_SEL_TIMER_MASK) << | ||
| 338 | ANA_INTERVAL_SEL_TIMER_SHIFT); | ||
| 339 | |||
| 340 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18); | ||
| 341 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 342 | |||
| 343 | data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG | | ||
| 344 | ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL | | ||
| 345 | ANA_SERDES_EN_LCKDT; | ||
| 346 | |||
| 347 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5); | ||
| 348 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 349 | |||
| 350 | data = (44 & ANA_LONG_CABLE_TH_100_MASK) | | ||
| 351 | ((33 & ANA_SHORT_CABLE_TH_100_MASK) << | ||
| 352 | ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM | | ||
| 353 | ANA_BP_SMALL_BW; | ||
| 354 | |||
| 355 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54); | ||
| 356 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 357 | |||
| 358 | data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) << | ||
| 359 | ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << | ||
| 360 | ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << | ||
| 361 | ANA_IECHO_ADJ_0_SHIFT); | ||
| 362 | |||
| 363 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4); | ||
| 364 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 365 | |||
| 366 | data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) << | ||
| 367 | ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE | | ||
| 368 | ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M; | ||
| 369 | |||
| 370 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0); | ||
| 371 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 372 | |||
| 373 | if (hw->ctrl_flags & ATL1C_HIB_DISABLE) { | ||
| 374 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41); | ||
| 375 | if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) | ||
| 376 | return; | ||
| 377 | data &= ~ANA_TOP_PS_EN; | ||
| 378 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 379 | |||
| 380 | atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11); | ||
| 381 | if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) | ||
| 382 | return; | ||
| 383 | data &= ~ANA_PS_HIB_EN; | ||
| 384 | atl1c_write_phy_reg(hw, MII_DBG_DATA, data); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | int atl1c_phy_reset(struct atl1c_hw *hw) | ||
| 389 | { | ||
| 390 | struct atl1c_adapter *adapter = hw->adapter; | ||
| 391 | struct pci_dev *pdev = adapter->pdev; | ||
| 392 | u32 phy_ctrl_data = GPHY_CTRL_DEFAULT; | ||
| 393 | u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN; | ||
| 394 | int err; | ||
| 395 | |||
| 396 | if (hw->ctrl_flags & ATL1C_HIB_DISABLE) | ||
| 397 | phy_ctrl_data &= ~GPHY_CTRL_HIB_EN; | ||
| 398 | |||
| 399 | AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); | ||
| 400 | AT_WRITE_FLUSH(hw); | ||
| 401 | msleep(40); | ||
| 402 | phy_ctrl_data |= GPHY_CTRL_EXT_RESET; | ||
| 403 | AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); | ||
| 404 | AT_WRITE_FLUSH(hw); | ||
| 405 | msleep(10); | ||
| 406 | |||
| 407 | /*Enable PHY LinkChange Interrupt */ | ||
| 408 | err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); | ||
| 409 | if (err) { | ||
| 410 | if (netif_msg_hw(adapter)) | ||
| 411 | dev_err(&pdev->dev, | ||
| 412 | "Error enable PHY linkChange Interrupt\n"); | ||
| 413 | return err; | ||
| 414 | } | ||
| 415 | if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) | ||
| 416 | atl1c_phy_magic_data(hw); | ||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | int atl1c_phy_init(struct atl1c_hw *hw) | ||
| 421 | { | ||
| 422 | struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; | ||
| 423 | struct pci_dev *pdev = adapter->pdev; | ||
| 424 | int ret_val; | ||
| 425 | u16 mii_bmcr_data = BMCR_RESET; | ||
| 426 | u16 phy_id1, phy_id2; | ||
| 427 | |||
| 428 | if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) || | ||
| 429 | (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) { | ||
| 430 | if (netif_msg_link(adapter)) | ||
| 431 | dev_err(&pdev->dev, "Error get phy ID\n"); | ||
| 432 | return -1; | ||
| 433 | } | ||
| 434 | switch (hw->media_type) { | ||
| 435 | case MEDIA_TYPE_AUTO_SENSOR: | ||
| 436 | ret_val = atl1c_phy_setup_adv(hw); | ||
| 437 | if (ret_val) { | ||
| 438 | if (netif_msg_link(adapter)) | ||
| 439 | dev_err(&pdev->dev, | ||
| 440 | "Error Setting up Auto-Negotiation\n"); | ||
| 441 | return ret_val; | ||
| 442 | } | ||
| 443 | mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG; | ||
| 444 | break; | ||
| 445 | case MEDIA_TYPE_100M_FULL: | ||
| 446 | mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX; | ||
| 447 | break; | ||
| 448 | case MEDIA_TYPE_100M_HALF: | ||
| 449 | mii_bmcr_data |= BMCR_SPEED_100; | ||
| 450 | break; | ||
| 451 | case MEDIA_TYPE_10M_FULL: | ||
| 452 | mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX; | ||
| 453 | break; | ||
| 454 | case MEDIA_TYPE_10M_HALF: | ||
| 455 | mii_bmcr_data |= BMCR_SPEED_10; | ||
| 456 | break; | ||
| 457 | default: | ||
| 458 | if (netif_msg_link(adapter)) | ||
| 459 | dev_err(&pdev->dev, "Wrong Media type %d\n", | ||
| 460 | hw->media_type); | ||
| 461 | return -1; | ||
| 462 | break; | ||
| 463 | } | ||
| 464 | |||
| 465 | ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); | ||
| 466 | if (ret_val) | ||
| 467 | return ret_val; | ||
| 468 | hw->phy_configured = true; | ||
| 469 | |||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * Detects the current speed and duplex settings of the hardware. | ||
| 475 | * | ||
| 476 | * hw - Struct containing variables accessed by shared code | ||
| 477 | * speed - Speed of the connection | ||
| 478 | * duplex - Duplex setting of the connection | ||
| 479 | */ | ||
| 480 | int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) | ||
| 481 | { | ||
| 482 | int err; | ||
| 483 | u16 phy_data; | ||
| 484 | |||
| 485 | /* Read PHY Specific Status Register (17) */ | ||
| 486 | err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data); | ||
| 487 | if (err) | ||
| 488 | return err; | ||
| 489 | |||
| 490 | if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED)) | ||
| 491 | return -1; | ||
| 492 | |||
| 493 | switch (phy_data & GIGA_PSSR_SPEED) { | ||
| 494 | case GIGA_PSSR_1000MBS: | ||
| 495 | *speed = SPEED_1000; | ||
| 496 | break; | ||
| 497 | case GIGA_PSSR_100MBS: | ||
| 498 | *speed = SPEED_100; | ||
| 499 | break; | ||
| 500 | case GIGA_PSSR_10MBS: | ||
| 501 | *speed = SPEED_10; | ||
| 502 | break; | ||
| 503 | default: | ||
| 504 | return -1; | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | |||
| 508 | if (phy_data & GIGA_PSSR_DPLX) | ||
| 509 | *duplex = FULL_DUPLEX; | ||
| 510 | else | ||
| 511 | *duplex = HALF_DUPLEX; | ||
| 512 | |||
| 513 | return 0; | ||
| 514 | } | ||
| 515 | |||
| 516 | int atl1c_restart_autoneg(struct atl1c_hw *hw) | ||
| 517 | { | ||
| 518 | int err = 0; | ||
| 519 | u16 mii_bmcr_data = BMCR_RESET; | ||
| 520 | |||
| 521 | err = atl1c_phy_setup_adv(hw); | ||
| 522 | if (err) | ||
| 523 | return err; | ||
| 524 | mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG; | ||
| 525 | |||
| 526 | return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); | ||
| 527 | } | ||
diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h new file mode 100644 index 00000000000..c2c738df5c6 --- /dev/null +++ b/drivers/net/atl1c/atl1c_hw.h | |||
| @@ -0,0 +1,859 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Derived from Intel e1000 driver | ||
| 5 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _ATL1C_HW_H_ | ||
| 23 | #define _ATL1C_HW_H_ | ||
| 24 | |||
| 25 | #include <linux/types.h> | ||
| 26 | #include <linux/mii.h> | ||
| 27 | |||
| 28 | struct atl1c_adapter; | ||
| 29 | struct atl1c_hw; | ||
| 30 | |||
| 31 | /* function prototype */ | ||
| 32 | void atl1c_phy_disable(struct atl1c_hw *hw); | ||
| 33 | void atl1c_hw_set_mac_addr(struct atl1c_hw *hw); | ||
| 34 | int atl1c_phy_reset(struct atl1c_hw *hw); | ||
| 35 | int atl1c_read_mac_addr(struct atl1c_hw *hw); | ||
| 36 | int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); | ||
| 37 | u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr); | ||
| 38 | void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value); | ||
| 39 | int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); | ||
| 40 | int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data); | ||
| 41 | bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); | ||
| 42 | int atl1c_phy_init(struct atl1c_hw *hw); | ||
| 43 | int atl1c_check_eeprom_exist(struct atl1c_hw *hw); | ||
| 44 | int atl1c_restart_autoneg(struct atl1c_hw *hw); | ||
| 45 | |||
| 46 | /* register definition */ | ||
| 47 | #define REG_DEVICE_CAP 0x5C | ||
| 48 | #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 | ||
| 49 | #define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 | ||
| 50 | |||
| 51 | #define REG_DEVICE_CTRL 0x60 | ||
| 52 | #define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 | ||
| 53 | #define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 | ||
| 54 | #define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 | ||
| 55 | #define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 | ||
| 56 | |||
| 57 | #define REG_LINK_CTRL 0x68 | ||
| 58 | #define LINK_CTRL_L0S_EN 0x01 | ||
| 59 | #define LINK_CTRL_L1_EN 0x02 | ||
| 60 | |||
| 61 | #define REG_VPD_CAP 0x6C | ||
| 62 | #define VPD_CAP_ID_MASK 0xff | ||
| 63 | #define VPD_CAP_ID_SHIFT 0 | ||
| 64 | #define VPD_CAP_NEXT_PTR_MASK 0xFF | ||
| 65 | #define VPD_CAP_NEXT_PTR_SHIFT 8 | ||
| 66 | #define VPD_CAP_VPD_ADDR_MASK 0x7FFF | ||
| 67 | #define VPD_CAP_VPD_ADDR_SHIFT 16 | ||
| 68 | #define VPD_CAP_VPD_FLAG 0x80000000 | ||
| 69 | |||
| 70 | #define REG_VPD_DATA 0x70 | ||
| 71 | |||
| 72 | #define REG_PCIE_UC_SEVERITY 0x10C | ||
| 73 | #define PCIE_UC_SERVRITY_TRN 0x00000001 | ||
| 74 | #define PCIE_UC_SERVRITY_DLP 0x00000010 | ||
| 75 | #define PCIE_UC_SERVRITY_PSN_TLP 0x00001000 | ||
| 76 | #define PCIE_UC_SERVRITY_FCP 0x00002000 | ||
| 77 | #define PCIE_UC_SERVRITY_CPL_TO 0x00004000 | ||
| 78 | #define PCIE_UC_SERVRITY_CA 0x00008000 | ||
| 79 | #define PCIE_UC_SERVRITY_UC 0x00010000 | ||
| 80 | #define PCIE_UC_SERVRITY_ROV 0x00020000 | ||
| 81 | #define PCIE_UC_SERVRITY_MLFP 0x00040000 | ||
| 82 | #define PCIE_UC_SERVRITY_ECRC 0x00080000 | ||
| 83 | #define PCIE_UC_SERVRITY_UR 0x00100000 | ||
| 84 | |||
| 85 | #define REG_DEV_SERIALNUM_CTRL 0x200 | ||
| 86 | #define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ | ||
| 87 | #define REG_DEV_MAC_SEL_SHIFT 0 | ||
| 88 | #define REG_DEV_SERIAL_NUM_EN_MASK 0x1 | ||
| 89 | #define REG_DEV_SERIAL_NUM_EN_SHIFT 1 | ||
| 90 | |||
| 91 | #define REG_TWSI_CTRL 0x218 | ||
| 92 | #define TWSI_CTRL_LD_OFFSET_MASK 0xFF | ||
| 93 | #define TWSI_CTRL_LD_OFFSET_SHIFT 0 | ||
| 94 | #define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 | ||
| 95 | #define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 | ||
| 96 | #define TWSI_CTRL_SW_LDSTART 0x800 | ||
| 97 | #define TWSI_CTRL_HW_LDSTART 0x1000 | ||
| 98 | #define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F | ||
| 99 | #define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 | ||
| 100 | #define TWSI_CTRL_LD_EXIST 0x400000 | ||
| 101 | #define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 | ||
| 102 | #define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 | ||
| 103 | #define TWSI_CTRL_FREQ_SEL_100K 0 | ||
| 104 | #define TWSI_CTRL_FREQ_SEL_200K 1 | ||
| 105 | #define TWSI_CTRL_FREQ_SEL_300K 2 | ||
| 106 | #define TWSI_CTRL_FREQ_SEL_400K 3 | ||
| 107 | #define TWSI_CTRL_SMB_SLV_ADDR | ||
| 108 | #define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 | ||
| 109 | #define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 | ||
| 110 | |||
| 111 | |||
| 112 | #define REG_PCIE_DEV_MISC_CTRL 0x21C | ||
| 113 | #define PCIE_DEV_MISC_EXT_PIPE 0x2 | ||
| 114 | #define PCIE_DEV_MISC_RETRY_BUFDIS 0x1 | ||
| 115 | #define PCIE_DEV_MISC_SPIROM_EXIST 0x4 | ||
| 116 | #define PCIE_DEV_MISC_SERDES_ENDIAN 0x8 | ||
| 117 | #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 | ||
| 118 | |||
| 119 | #define REG_PCIE_PHYMISC 0x1000 | ||
| 120 | #define PCIE_PHYMISC_FORCE_RCV_DET 0x4 | ||
| 121 | |||
| 122 | #define REG_TWSI_DEBUG 0x1108 | ||
| 123 | #define TWSI_DEBUG_DEV_EXIST 0x20000000 | ||
| 124 | |||
| 125 | #define REG_EEPROM_CTRL 0x12C0 | ||
| 126 | #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF | ||
| 127 | #define EEPROM_CTRL_DATA_HI_SHIFT 0 | ||
| 128 | #define EEPROM_CTRL_ADDR_MASK 0x3FF | ||
| 129 | #define EEPROM_CTRL_ADDR_SHIFT 16 | ||
| 130 | #define EEPROM_CTRL_ACK 0x40000000 | ||
| 131 | #define EEPROM_CTRL_RW 0x80000000 | ||
| 132 | |||
| 133 | #define REG_EEPROM_DATA_LO 0x12C4 | ||
| 134 | |||
| 135 | #define REG_OTP_CTRL 0x12F0 | ||
| 136 | #define OTP_CTRL_CLK_EN 0x0002 | ||
| 137 | |||
| 138 | #define REG_PM_CTRL 0x12F8 | ||
| 139 | #define PM_CTRL_SDES_EN 0x00000001 | ||
| 140 | #define PM_CTRL_RBER_EN 0x00000002 | ||
| 141 | #define PM_CTRL_CLK_REQ_EN 0x00000004 | ||
| 142 | #define PM_CTRL_ASPM_L1_EN 0x00000008 | ||
| 143 | #define PM_CTRL_SERDES_L1_EN 0x00000010 | ||
| 144 | #define PM_CTRL_SERDES_PLL_L1_EN 0x00000020 | ||
| 145 | #define PM_CTRL_SERDES_PD_EX_L1 0x00000040 | ||
| 146 | #define PM_CTRL_SERDES_BUDS_RX_L1_EN 0x00000080 | ||
| 147 | #define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xF | ||
| 148 | #define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 | ||
| 149 | #define PM_CTRL_ASPM_L0S_EN 0x00001000 | ||
| 150 | #define PM_CTRL_CLK_SWH_L1 0x00002000 | ||
| 151 | #define PM_CTRL_CLK_PWM_VER1_1 0x00004000 | ||
| 152 | #define PM_CTRL_PCIE_RECV 0x00008000 | ||
| 153 | #define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF | ||
| 154 | #define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 | ||
| 155 | #define PM_CTRL_PM_REQ_TIMER_MASK 0xF | ||
| 156 | #define PM_CTRL_PM_REQ_TIMER_SHIFT 20 | ||
| 157 | #define PM_CTRL_LCKDET_TIMER_MASK 0x3F | ||
| 158 | #define PM_CTRL_LCKDET_TIMER_SHIFT 24 | ||
| 159 | #define PM_CTRL_MAC_ASPM_CHK 0x40000000 | ||
| 160 | #define PM_CTRL_HOTRST 0x80000000 | ||
| 161 | |||
| 162 | /* Selene Master Control Register */ | ||
| 163 | #define REG_MASTER_CTRL 0x1400 | ||
| 164 | #define MASTER_CTRL_SOFT_RST 0x1 | ||
| 165 | #define MASTER_CTRL_TEST_MODE_MASK 0x3 | ||
| 166 | #define MASTER_CTRL_TEST_MODE_SHIFT 2 | ||
| 167 | #define MASTER_CTRL_BERT_START 0x10 | ||
| 168 | #define MASTER_CTRL_MTIMER_EN 0x100 | ||
| 169 | #define MASTER_CTRL_MANUAL_INT 0x200 | ||
| 170 | #define MASTER_CTRL_TX_ITIMER_EN 0x400 | ||
| 171 | #define MASTER_CTRL_RX_ITIMER_EN 0x800 | ||
| 172 | #define MASTER_CTRL_CLK_SEL_DIS 0x1000 | ||
| 173 | #define MASTER_CTRL_CLK_SWH_MODE 0x2000 | ||
| 174 | #define MASTER_CTRL_INT_RDCLR 0x4000 | ||
| 175 | #define MASTER_CTRL_REV_NUM_SHIFT 16 | ||
| 176 | #define MASTER_CTRL_REV_NUM_MASK 0xff | ||
| 177 | #define MASTER_CTRL_DEV_ID_SHIFT 24 | ||
| 178 | #define MASTER_CTRL_DEV_ID_MASK 0x7f | ||
| 179 | #define MASTER_CTRL_OTP_SEL 0x80000000 | ||
| 180 | |||
| 181 | /* Timer Initial Value Register */ | ||
| 182 | #define REG_MANUAL_TIMER_INIT 0x1404 | ||
| 183 | |||
| 184 | /* IRQ ModeratorTimer Initial Value Register */ | ||
| 185 | #define REG_IRQ_MODRT_TIMER_INIT 0x1408 | ||
| 186 | #define IRQ_MODRT_TIMER_MASK 0xffff | ||
| 187 | #define IRQ_MODRT_TX_TIMER_SHIFT 0 | ||
| 188 | #define IRQ_MODRT_RX_TIMER_SHIFT 16 | ||
| 189 | |||
| 190 | #define REG_GPHY_CTRL 0x140C | ||
| 191 | #define GPHY_CTRL_EXT_RESET 0x1 | ||
| 192 | #define GPHY_CTRL_RTL_MODE 0x2 | ||
| 193 | #define GPHY_CTRL_LED_MODE 0x4 | ||
| 194 | #define GPHY_CTRL_ANEG_NOW 0x8 | ||
| 195 | #define GPHY_CTRL_REV_ANEG 0x10 | ||
| 196 | #define GPHY_CTRL_GATE_25M_EN 0x20 | ||
| 197 | #define GPHY_CTRL_LPW_EXIT 0x40 | ||
| 198 | #define GPHY_CTRL_PHY_IDDQ 0x80 | ||
| 199 | #define GPHY_CTRL_PHY_IDDQ_DIS 0x100 | ||
| 200 | #define GPHY_CTRL_GIGA_DIS 0x200 | ||
| 201 | #define GPHY_CTRL_HIB_EN 0x400 | ||
| 202 | #define GPHY_CTRL_HIB_PULSE 0x800 | ||
| 203 | #define GPHY_CTRL_SEL_ANA_RST 0x1000 | ||
| 204 | #define GPHY_CTRL_PHY_PLL_ON 0x2000 | ||
| 205 | #define GPHY_CTRL_PWDOWN_HW 0x4000 | ||
| 206 | #define GPHY_CTRL_PHY_PLL_BYPASS 0x8000 | ||
| 207 | |||
| 208 | #define GPHY_CTRL_DEFAULT ( \ | ||
| 209 | GPHY_CTRL_SEL_ANA_RST |\ | ||
| 210 | GPHY_CTRL_HIB_PULSE |\ | ||
| 211 | GPHY_CTRL_HIB_EN) | ||
| 212 | |||
| 213 | #define GPHY_CTRL_PW_WOL_DIS ( \ | ||
| 214 | GPHY_CTRL_SEL_ANA_RST |\ | ||
| 215 | GPHY_CTRL_HIB_PULSE |\ | ||
| 216 | GPHY_CTRL_HIB_EN |\ | ||
| 217 | GPHY_CTRL_PWDOWN_HW |\ | ||
| 218 | GPHY_CTRL_PHY_IDDQ) | ||
| 219 | |||
| 220 | /* Block IDLE Status Register */ | ||
| 221 | #define REG_IDLE_STATUS 0x1410 | ||
| 222 | #define IDLE_STATUS_MASK 0x00FF | ||
| 223 | #define IDLE_STATUS_RXMAC_NO_IDLE 0x1 | ||
| 224 | #define IDLE_STATUS_TXMAC_NO_IDLE 0x2 | ||
| 225 | #define IDLE_STATUS_RXQ_NO_IDLE 0x4 | ||
| 226 | #define IDLE_STATUS_TXQ_NO_IDLE 0x8 | ||
| 227 | #define IDLE_STATUS_DMAR_NO_IDLE 0x10 | ||
| 228 | #define IDLE_STATUS_DMAW_NO_IDLE 0x20 | ||
| 229 | #define IDLE_STATUS_SMB_NO_IDLE 0x40 | ||
| 230 | #define IDLE_STATUS_CMB_NO_IDLE 0x80 | ||
| 231 | |||
| 232 | /* MDIO Control Register */ | ||
| 233 | #define REG_MDIO_CTRL 0x1414 | ||
| 234 | #define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit | ||
| 235 | * control data to write to PHY | ||
| 236 | * MII management register */ | ||
| 237 | #define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit | ||
| 238 | * status data that was read | ||
| 239 | * from the PHY MII management register */ | ||
| 240 | #define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ | ||
| 241 | #define MDIO_REG_ADDR_SHIFT 16 | ||
| 242 | #define MDIO_RW 0x200000 /* 1: read, 0: write */ | ||
| 243 | #define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ | ||
| 244 | #define MDIO_START 0x800000 /* Write 1 to initiate the MDIO | ||
| 245 | * master. And this bit is self | ||
| 246 | * cleared after one cycle */ | ||
| 247 | #define MDIO_CLK_SEL_SHIFT 24 | ||
| 248 | #define MDIO_CLK_25_4 0 | ||
| 249 | #define MDIO_CLK_25_6 2 | ||
| 250 | #define MDIO_CLK_25_8 3 | ||
| 251 | #define MDIO_CLK_25_10 4 | ||
| 252 | #define MDIO_CLK_25_14 5 | ||
| 253 | #define MDIO_CLK_25_20 6 | ||
| 254 | #define MDIO_CLK_25_28 7 | ||
| 255 | #define MDIO_BUSY 0x8000000 | ||
| 256 | #define MDIO_AP_EN 0x10000000 | ||
| 257 | #define MDIO_WAIT_TIMES 10 | ||
| 258 | |||
| 259 | /* MII PHY Status Register */ | ||
| 260 | #define REG_PHY_STATUS 0x1418 | ||
| 261 | #define PHY_GENERAL_STATUS_MASK 0xFFFF | ||
| 262 | #define PHY_STATUS_RECV_ENABLE 0x0001 | ||
| 263 | #define PHY_OE_PWSP_STATUS_MASK 0x07FF | ||
| 264 | #define PHY_OE_PWSP_STATUS_SHIFT 16 | ||
| 265 | #define PHY_STATUS_LPW_STATE 0x80000000 | ||
| 266 | /* BIST Control and Status Register0 (for the Packet Memory) */ | ||
| 267 | #define REG_BIST0_CTRL 0x141c | ||
| 268 | #define BIST0_NOW 0x1 | ||
| 269 | #define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is | ||
| 270 | * un-repairable because | ||
| 271 | * it has address decoder | ||
| 272 | * failure or more than 1 cell | ||
| 273 | * stuck-to-x failure */ | ||
| 274 | #define BIST0_FUSE_FLAG 0x4 | ||
| 275 | |||
| 276 | /* BIST Control and Status Register1(for the retry buffer of PCI Express) */ | ||
| 277 | #define REG_BIST1_CTRL 0x1420 | ||
| 278 | #define BIST1_NOW 0x1 | ||
| 279 | #define BIST1_SRAM_FAIL 0x2 | ||
| 280 | #define BIST1_FUSE_FLAG 0x4 | ||
| 281 | |||
| 282 | /* SerDes Lock Detect Control and Status Register */ | ||
| 283 | #define REG_SERDES_LOCK 0x1424 | ||
| 284 | #define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal | ||
| 285 | * comes from Analog SerDes */ | ||
| 286 | #define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */ | ||
| 287 | |||
| 288 | /* MAC Control Register */ | ||
| 289 | #define REG_MAC_CTRL 0x1480 | ||
| 290 | #define MAC_CTRL_TX_EN 0x1 | ||
| 291 | #define MAC_CTRL_RX_EN 0x2 | ||
| 292 | #define MAC_CTRL_TX_FLOW 0x4 | ||
| 293 | #define MAC_CTRL_RX_FLOW 0x8 | ||
| 294 | #define MAC_CTRL_LOOPBACK 0x10 | ||
| 295 | #define MAC_CTRL_DUPLX 0x20 | ||
| 296 | #define MAC_CTRL_ADD_CRC 0x40 | ||
| 297 | #define MAC_CTRL_PAD 0x80 | ||
| 298 | #define MAC_CTRL_LENCHK 0x100 | ||
| 299 | #define MAC_CTRL_HUGE_EN 0x200 | ||
| 300 | #define MAC_CTRL_PRMLEN_SHIFT 10 | ||
| 301 | #define MAC_CTRL_PRMLEN_MASK 0xf | ||
| 302 | #define MAC_CTRL_RMV_VLAN 0x4000 | ||
| 303 | #define MAC_CTRL_PROMIS_EN 0x8000 | ||
| 304 | #define MAC_CTRL_TX_PAUSE 0x10000 | ||
| 305 | #define MAC_CTRL_SCNT 0x20000 | ||
| 306 | #define MAC_CTRL_SRST_TX 0x40000 | ||
| 307 | #define MAC_CTRL_TX_SIMURST 0x80000 | ||
| 308 | #define MAC_CTRL_SPEED_SHIFT 20 | ||
| 309 | #define MAC_CTRL_SPEED_MASK 0x3 | ||
| 310 | #define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 | ||
| 311 | #define MAC_CTRL_TX_HUGE 0x800000 | ||
| 312 | #define MAC_CTRL_RX_CHKSUM_EN 0x1000000 | ||
| 313 | #define MAC_CTRL_MC_ALL_EN 0x2000000 | ||
| 314 | #define MAC_CTRL_BC_EN 0x4000000 | ||
| 315 | #define MAC_CTRL_DBG 0x8000000 | ||
| 316 | #define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 | ||
| 317 | |||
| 318 | /* MAC IPG/IFG Control Register */ | ||
| 319 | #define REG_MAC_IPG_IFG 0x1484 | ||
| 320 | #define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back | ||
| 321 | * inter-packet gap. The | ||
| 322 | * default is 96-bit time */ | ||
| 323 | #define MAC_IPG_IFG_IPGT_MASK 0x7f | ||
| 324 | #define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to | ||
| 325 | * enforce in between RX frames */ | ||
| 326 | #define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */ | ||
| 327 | #define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ | ||
| 328 | #define MAC_IPG_IFG_IPGR1_MASK 0x7f | ||
| 329 | #define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ | ||
| 330 | #define MAC_IPG_IFG_IPGR2_MASK 0x7f | ||
| 331 | |||
| 332 | /* MAC STATION ADDRESS */ | ||
| 333 | #define REG_MAC_STA_ADDR 0x1488 | ||
| 334 | |||
| 335 | /* Hash table for multicast address */ | ||
| 336 | #define REG_RX_HASH_TABLE 0x1490 | ||
| 337 | |||
| 338 | /* MAC Half-Duplex Control Register */ | ||
| 339 | #define REG_MAC_HALF_DUPLX_CTRL 0x1498 | ||
| 340 | #define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */ | ||
| 341 | #define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff | ||
| 342 | #define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 | ||
| 343 | #define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf | ||
| 344 | #define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 | ||
| 345 | #define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 | ||
| 346 | #define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* No back-off on backpressure, | ||
| 347 | * immediately start the | ||
| 348 | * transmission after back pressure */ | ||
| 349 | #define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ | ||
| 350 | #define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */ | ||
| 351 | #define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf | ||
| 352 | #define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ | ||
| 353 | #define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */ | ||
| 354 | |||
| 355 | /* Maximum Frame Length Control Register */ | ||
| 356 | #define REG_MTU 0x149c | ||
| 357 | |||
| 358 | /* Wake-On-Lan control register */ | ||
| 359 | #define REG_WOL_CTRL 0x14a0 | ||
| 360 | #define WOL_PATTERN_EN 0x00000001 | ||
| 361 | #define WOL_PATTERN_PME_EN 0x00000002 | ||
| 362 | #define WOL_MAGIC_EN 0x00000004 | ||
| 363 | #define WOL_MAGIC_PME_EN 0x00000008 | ||
| 364 | #define WOL_LINK_CHG_EN 0x00000010 | ||
| 365 | #define WOL_LINK_CHG_PME_EN 0x00000020 | ||
| 366 | #define WOL_PATTERN_ST 0x00000100 | ||
| 367 | #define WOL_MAGIC_ST 0x00000200 | ||
| 368 | #define WOL_LINKCHG_ST 0x00000400 | ||
| 369 | #define WOL_CLK_SWITCH_EN 0x00008000 | ||
| 370 | #define WOL_PT0_EN 0x00010000 | ||
| 371 | #define WOL_PT1_EN 0x00020000 | ||
| 372 | #define WOL_PT2_EN 0x00040000 | ||
| 373 | #define WOL_PT3_EN 0x00080000 | ||
| 374 | #define WOL_PT4_EN 0x00100000 | ||
| 375 | #define WOL_PT5_EN 0x00200000 | ||
| 376 | #define WOL_PT6_EN 0x00400000 | ||
| 377 | |||
| 378 | /* WOL Length ( 2 DWORD ) */ | ||
| 379 | #define REG_WOL_PATTERN_LEN 0x14a4 | ||
| 380 | #define WOL_PT_LEN_MASK 0x7f | ||
| 381 | #define WOL_PT0_LEN_SHIFT 0 | ||
| 382 | #define WOL_PT1_LEN_SHIFT 8 | ||
| 383 | #define WOL_PT2_LEN_SHIFT 16 | ||
| 384 | #define WOL_PT3_LEN_SHIFT 24 | ||
| 385 | #define WOL_PT4_LEN_SHIFT 0 | ||
| 386 | #define WOL_PT5_LEN_SHIFT 8 | ||
| 387 | #define WOL_PT6_LEN_SHIFT 16 | ||
| 388 | |||
| 389 | /* Internal SRAM Partition Register */ | ||
| 390 | #define RFDX_HEAD_ADDR_MASK 0x03FF | ||
| 391 | #define RFDX_HARD_ADDR_SHIFT 0 | ||
| 392 | #define RFDX_TAIL_ADDR_MASK 0x03FF | ||
| 393 | #define RFDX_TAIL_ADDR_SHIFT 16 | ||
| 394 | |||
| 395 | #define REG_SRAM_RFD0_INFO 0x1500 | ||
| 396 | #define REG_SRAM_RFD1_INFO 0x1504 | ||
| 397 | #define REG_SRAM_RFD2_INFO 0x1508 | ||
| 398 | #define REG_SRAM_RFD3_INFO 0x150C | ||
| 399 | |||
| 400 | #define REG_RFD_NIC_LEN 0x1510 /* In 8-bytes */ | ||
| 401 | #define RFD_NIC_LEN_MASK 0x03FF | ||
| 402 | |||
| 403 | #define REG_SRAM_TRD_ADDR 0x1518 | ||
| 404 | #define TPD_HEAD_ADDR_MASK 0x03FF | ||
| 405 | #define TPD_HEAD_ADDR_SHIFT 0 | ||
| 406 | #define TPD_TAIL_ADDR_MASK 0x03FF | ||
| 407 | #define TPD_TAIL_ADDR_SHIFT 16 | ||
| 408 | |||
| 409 | #define REG_SRAM_TRD_LEN 0x151C /* In 8-bytes */ | ||
| 410 | #define TPD_NIC_LEN_MASK 0x03FF | ||
| 411 | |||
| 412 | #define REG_SRAM_RXF_ADDR 0x1520 | ||
| 413 | #define REG_SRAM_RXF_LEN 0x1524 | ||
| 414 | #define REG_SRAM_TXF_ADDR 0x1528 | ||
| 415 | #define REG_SRAM_TXF_LEN 0x152C | ||
| 416 | #define REG_SRAM_TCPH_ADDR 0x1530 | ||
| 417 | #define REG_SRAM_PKTH_ADDR 0x1532 | ||
| 418 | |||
| 419 | /* | ||
| 420 | * Load Ptr Register | ||
| 421 | * Software sets this bit after the initialization of the head and tail */ | ||
| 422 | #define REG_LOAD_PTR 0x1534 | ||
| 423 | |||
| 424 | /* | ||
| 425 | * addresses of all descriptors, as well as the following descriptor | ||
| 426 | * control register, which triggers each function block to load the head | ||
| 427 | * pointer to prepare for the operation. This bit is then self-cleared | ||
| 428 | * after one cycle. | ||
| 429 | */ | ||
| 430 | #define REG_RX_BASE_ADDR_HI 0x1540 | ||
| 431 | #define REG_TX_BASE_ADDR_HI 0x1544 | ||
| 432 | #define REG_SMB_BASE_ADDR_HI 0x1548 | ||
| 433 | #define REG_SMB_BASE_ADDR_LO 0x154C | ||
| 434 | #define REG_RFD0_HEAD_ADDR_LO 0x1550 | ||
| 435 | #define REG_RFD1_HEAD_ADDR_LO 0x1554 | ||
| 436 | #define REG_RFD2_HEAD_ADDR_LO 0x1558 | ||
| 437 | #define REG_RFD3_HEAD_ADDR_LO 0x155C | ||
| 438 | #define REG_RFD_RING_SIZE 0x1560 | ||
| 439 | #define RFD_RING_SIZE_MASK 0x0FFF | ||
| 440 | #define REG_RX_BUF_SIZE 0x1564 | ||
| 441 | #define RX_BUF_SIZE_MASK 0xFFFF | ||
| 442 | #define REG_RRD0_HEAD_ADDR_LO 0x1568 | ||
| 443 | #define REG_RRD1_HEAD_ADDR_LO 0x156C | ||
| 444 | #define REG_RRD2_HEAD_ADDR_LO 0x1570 | ||
| 445 | #define REG_RRD3_HEAD_ADDR_LO 0x1574 | ||
| 446 | #define REG_RRD_RING_SIZE 0x1578 | ||
| 447 | #define RRD_RING_SIZE_MASK 0x0FFF | ||
| 448 | #define REG_HTPD_HEAD_ADDR_LO 0x157C | ||
| 449 | #define REG_NTPD_HEAD_ADDR_LO 0x1580 | ||
| 450 | #define REG_TPD_RING_SIZE 0x1584 | ||
| 451 | #define TPD_RING_SIZE_MASK 0xFFFF | ||
| 452 | #define REG_CMB_BASE_ADDR_LO 0x1588 | ||
| 453 | |||
| 454 | /* RSS about */ | ||
| 455 | #define REG_RSS_KEY0 0x14B0 | ||
| 456 | #define REG_RSS_KEY1 0x14B4 | ||
| 457 | #define REG_RSS_KEY2 0x14B8 | ||
| 458 | #define REG_RSS_KEY3 0x14BC | ||
| 459 | #define REG_RSS_KEY4 0x14C0 | ||
| 460 | #define REG_RSS_KEY5 0x14C4 | ||
| 461 | #define REG_RSS_KEY6 0x14C8 | ||
| 462 | #define REG_RSS_KEY7 0x14CC | ||
| 463 | #define REG_RSS_KEY8 0x14D0 | ||
| 464 | #define REG_RSS_KEY9 0x14D4 | ||
| 465 | #define REG_IDT_TABLE0 0x14E0 | ||
| 466 | #define REG_IDT_TABLE1 0x14E4 | ||
| 467 | #define REG_IDT_TABLE2 0x14E8 | ||
| 468 | #define REG_IDT_TABLE3 0x14EC | ||
| 469 | #define REG_IDT_TABLE4 0x14F0 | ||
| 470 | #define REG_IDT_TABLE5 0x14F4 | ||
| 471 | #define REG_IDT_TABLE6 0x14F8 | ||
| 472 | #define REG_IDT_TABLE7 0x14FC | ||
| 473 | #define REG_IDT_TABLE REG_IDT_TABLE0 | ||
| 474 | #define REG_RSS_HASH_VALUE 0x15B0 | ||
| 475 | #define REG_RSS_HASH_FLAG 0x15B4 | ||
| 476 | #define REG_BASE_CPU_NUMBER 0x15B8 | ||
| 477 | |||
| 478 | /* TXQ Control Register */ | ||
| 479 | #define REG_TXQ_CTRL 0x1590 | ||
| 480 | #define TXQ_NUM_TPD_BURST_MASK 0xF | ||
| 481 | #define TXQ_NUM_TPD_BURST_SHIFT 0 | ||
| 482 | #define TXQ_CTRL_IP_OPTION_EN 0x10 | ||
| 483 | #define TXQ_CTRL_EN 0x20 | ||
| 484 | #define TXQ_CTRL_ENH_MODE 0x40 | ||
| 485 | #define TXQ_CTRL_LS_8023_EN 0x80 | ||
| 486 | #define TXQ_TXF_BURST_NUM_SHIFT 16 | ||
| 487 | #define TXQ_TXF_BURST_NUM_MASK 0xFFFF | ||
| 488 | |||
| 489 | /* Jumbo packet Threshold for task offload */ | ||
| 490 | #define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ | ||
| 491 | #define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF | ||
| 492 | |||
| 493 | #define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ | ||
| 494 | #define TXF_WATER_MARK_MASK 0x0FFF | ||
| 495 | #define TXF_LOW_WATER_MARK_SHIFT 0 | ||
| 496 | #define TXF_HIGH_WATER_MARK_SHIFT 16 | ||
| 497 | #define TXQ_CTRL_BURST_MODE_EN 0x80000000 | ||
| 498 | |||
| 499 | #define REG_THRUPUT_MON_CTRL 0x159C | ||
| 500 | #define THRUPUT_MON_RATE_MASK 0x3 | ||
| 501 | #define THRUPUT_MON_RATE_SHIFT 0 | ||
| 502 | #define THRUPUT_MON_EN 0x80 | ||
| 503 | |||
| 504 | /* RXQ Control Register */ | ||
| 505 | #define REG_RXQ_CTRL 0x15A0 | ||
| 506 | #define ASPM_THRUPUT_LIMIT_MASK 0x3 | ||
| 507 | #define ASPM_THRUPUT_LIMIT_SHIFT 0 | ||
| 508 | #define ASPM_THRUPUT_LIMIT_NO 0x00 | ||
| 509 | #define ASPM_THRUPUT_LIMIT_1M 0x01 | ||
| 510 | #define ASPM_THRUPUT_LIMIT_10M 0x02 | ||
| 511 | #define ASPM_THRUPUT_LIMIT_100M 0x04 | ||
| 512 | #define RXQ1_CTRL_EN 0x10 | ||
| 513 | #define RXQ2_CTRL_EN 0x20 | ||
| 514 | #define RXQ3_CTRL_EN 0x40 | ||
| 515 | #define IPV6_CHKSUM_CTRL_EN 0x80 | ||
| 516 | #define RSS_HASH_BITS_MASK 0x00FF | ||
| 517 | #define RSS_HASH_BITS_SHIFT 8 | ||
| 518 | #define RSS_HASH_IPV4 0x10000 | ||
| 519 | #define RSS_HASH_IPV4_TCP 0x20000 | ||
| 520 | #define RSS_HASH_IPV6 0x40000 | ||
| 521 | #define RSS_HASH_IPV6_TCP 0x80000 | ||
| 522 | #define RXQ_RFD_BURST_NUM_MASK 0x003F | ||
| 523 | #define RXQ_RFD_BURST_NUM_SHIFT 20 | ||
| 524 | #define RSS_MODE_MASK 0x0003 | ||
| 525 | #define RSS_MODE_SHIFT 26 | ||
| 526 | #define RSS_NIP_QUEUE_SEL_MASK 0x1 | ||
| 527 | #define RSS_NIP_QUEUE_SEL_SHIFT 28 | ||
| 528 | #define RRS_HASH_CTRL_EN 0x20000000 | ||
| 529 | #define RX_CUT_THRU_EN 0x40000000 | ||
| 530 | #define RXQ_CTRL_EN 0x80000000 | ||
| 531 | |||
| 532 | #define REG_RFD_FREE_THRESH 0x15A4 | ||
| 533 | #define RFD_FREE_THRESH_MASK 0x003F | ||
| 534 | #define RFD_FREE_HI_THRESH_SHIFT 0 | ||
| 535 | #define RFD_FREE_LO_THRESH_SHIFT 6 | ||
| 536 | |||
| 537 | /* RXF flow control register */ | ||
| 538 | #define REG_RXQ_RXF_PAUSE_THRESH 0x15A8 | ||
| 539 | #define RXQ_RXF_PAUSE_TH_HI_SHIFT 0 | ||
| 540 | #define RXQ_RXF_PAUSE_TH_HI_MASK 0x0FFF | ||
| 541 | #define RXQ_RXF_PAUSE_TH_LO_SHIFT 16 | ||
| 542 | #define RXQ_RXF_PAUSE_TH_LO_MASK 0x0FFF | ||
| 543 | |||
| 544 | #define REG_RXD_DMA_CTRL 0x15AC | ||
| 545 | #define RXD_DMA_THRESH_MASK 0x0FFF /* In 8-bytes */ | ||
| 546 | #define RXD_DMA_THRESH_SHIFT 0 | ||
| 547 | #define RXD_DMA_DOWN_TIMER_MASK 0xFFFF | ||
| 548 | #define RXD_DMA_DOWN_TIMER_SHIFT 16 | ||
| 549 | |||
| 550 | /* DMA Engine Control Register */ | ||
| 551 | #define REG_DMA_CTRL 0x15C0 | ||
| 552 | #define DMA_CTRL_DMAR_IN_ORDER 0x1 | ||
| 553 | #define DMA_CTRL_DMAR_ENH_ORDER 0x2 | ||
| 554 | #define DMA_CTRL_DMAR_OUT_ORDER 0x4 | ||
| 555 | #define DMA_CTRL_RCB_VALUE 0x8 | ||
| 556 | #define DMA_CTRL_DMAR_BURST_LEN_MASK 0x0007 | ||
| 557 | #define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 | ||
| 558 | #define DMA_CTRL_DMAW_BURST_LEN_MASK 0x0007 | ||
| 559 | #define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 | ||
| 560 | #define DMA_CTRL_DMAR_REQ_PRI 0x400 | ||
| 561 | #define DMA_CTRL_DMAR_DLY_CNT_MASK 0x001F | ||
| 562 | #define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 | ||
| 563 | #define DMA_CTRL_DMAW_DLY_CNT_MASK 0x000F | ||
| 564 | #define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 | ||
| 565 | #define DMA_CTRL_CMB_EN 0x100000 | ||
| 566 | #define DMA_CTRL_SMB_EN 0x200000 | ||
| 567 | #define DMA_CTRL_CMB_NOW 0x400000 | ||
| 568 | #define MAC_CTRL_SMB_DIS 0x1000000 | ||
| 569 | #define DMA_CTRL_SMB_NOW 0x80000000 | ||
| 570 | |||
| 571 | /* CMB/SMB Control Register */ | ||
| 572 | #define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ | ||
| 573 | #define SMB_STAT_TIMER_MASK 0xFFFFFF | ||
| 574 | #define REG_CMB_TPD_THRESH 0x15C8 | ||
| 575 | #define CMB_TPD_THRESH_MASK 0xFFFF | ||
| 576 | #define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */ | ||
| 577 | #define CMB_TX_TIMER_MASK 0xFFFF | ||
| 578 | |||
| 579 | /* Mail box */ | ||
| 580 | #define MB_RFDX_PROD_IDX_MASK 0xFFFF | ||
| 581 | #define REG_MB_RFD0_PROD_IDX 0x15E0 | ||
| 582 | #define REG_MB_RFD1_PROD_IDX 0x15E4 | ||
| 583 | #define REG_MB_RFD2_PROD_IDX 0x15E8 | ||
| 584 | #define REG_MB_RFD3_PROD_IDX 0x15EC | ||
| 585 | |||
| 586 | #define MB_PRIO_PROD_IDX_MASK 0xFFFF | ||
| 587 | #define REG_MB_PRIO_PROD_IDX 0x15F0 | ||
| 588 | #define MB_HTPD_PROD_IDX_SHIFT 0 | ||
| 589 | #define MB_NTPD_PROD_IDX_SHIFT 16 | ||
| 590 | |||
| 591 | #define MB_PRIO_CONS_IDX_MASK 0xFFFF | ||
| 592 | #define REG_MB_PRIO_CONS_IDX 0x15F4 | ||
| 593 | #define MB_HTPD_CONS_IDX_SHIFT 0 | ||
| 594 | #define MB_NTPD_CONS_IDX_SHIFT 16 | ||
| 595 | |||
| 596 | #define REG_MB_RFD01_CONS_IDX 0x15F8 | ||
| 597 | #define MB_RFD0_CONS_IDX_MASK 0x0000FFFF | ||
| 598 | #define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 | ||
| 599 | #define REG_MB_RFD23_CONS_IDX 0x15FC | ||
| 600 | #define MB_RFD2_CONS_IDX_MASK 0x0000FFFF | ||
| 601 | #define MB_RFD3_CONS_IDX_MASK 0xFFFF0000 | ||
| 602 | |||
| 603 | /* Interrupt Status Register */ | ||
| 604 | #define REG_ISR 0x1600 | ||
| 605 | #define ISR_SMB 0x00000001 | ||
| 606 | #define ISR_TIMER 0x00000002 | ||
| 607 | /* | ||
| 608 | * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set | ||
| 609 | * in Table 51 Selene Master Control Register (Offset 0x1400). | ||
| 610 | */ | ||
| 611 | #define ISR_MANUAL 0x00000004 | ||
| 612 | #define ISR_HW_RXF_OV 0x00000008 /* RXF overflow interrupt */ | ||
| 613 | #define ISR_RFD0_UR 0x00000010 /* RFD0 under run */ | ||
| 614 | #define ISR_RFD1_UR 0x00000020 | ||
| 615 | #define ISR_RFD2_UR 0x00000040 | ||
| 616 | #define ISR_RFD3_UR 0x00000080 | ||
| 617 | #define ISR_TXF_UR 0x00000100 | ||
| 618 | #define ISR_DMAR_TO_RST 0x00000200 | ||
| 619 | #define ISR_DMAW_TO_RST 0x00000400 | ||
| 620 | #define ISR_TX_CREDIT 0x00000800 | ||
| 621 | #define ISR_GPHY 0x00001000 | ||
| 622 | /* GPHY low power state interrupt */ | ||
| 623 | #define ISR_GPHY_LPW 0x00002000 | ||
| 624 | #define ISR_TXQ_TO_RST 0x00004000 | ||
| 625 | #define ISR_TX_PKT 0x00008000 | ||
| 626 | #define ISR_RX_PKT_0 0x00010000 | ||
| 627 | #define ISR_RX_PKT_1 0x00020000 | ||
| 628 | #define ISR_RX_PKT_2 0x00040000 | ||
| 629 | #define ISR_RX_PKT_3 0x00080000 | ||
| 630 | #define ISR_MAC_RX 0x00100000 | ||
| 631 | #define ISR_MAC_TX 0x00200000 | ||
| 632 | #define ISR_UR_DETECTED 0x00400000 | ||
| 633 | #define ISR_FERR_DETECTED 0x00800000 | ||
| 634 | #define ISR_NFERR_DETECTED 0x01000000 | ||
| 635 | #define ISR_CERR_DETECTED 0x02000000 | ||
| 636 | #define ISR_PHY_LINKDOWN 0x04000000 | ||
| 637 | #define ISR_DIS_INT 0x80000000 | ||
| 638 | |||
| 639 | /* Interrupt Mask Register */ | ||
| 640 | #define REG_IMR 0x1604 | ||
| 641 | |||
| 642 | #define IMR_NORMAL_MASK (\ | ||
| 643 | ISR_MANUAL |\ | ||
| 644 | ISR_HW_RXF_OV |\ | ||
| 645 | ISR_RFD0_UR |\ | ||
| 646 | ISR_TXF_UR |\ | ||
| 647 | ISR_DMAR_TO_RST |\ | ||
| 648 | ISR_TXQ_TO_RST |\ | ||
| 649 | ISR_DMAW_TO_RST |\ | ||
| 650 | ISR_GPHY |\ | ||
| 651 | ISR_TX_PKT |\ | ||
| 652 | ISR_RX_PKT_0 |\ | ||
| 653 | ISR_GPHY_LPW |\ | ||
| 654 | ISR_PHY_LINKDOWN) | ||
| 655 | |||
| 656 | #define ISR_RX_PKT (\ | ||
| 657 | ISR_RX_PKT_0 |\ | ||
| 658 | ISR_RX_PKT_1 |\ | ||
| 659 | ISR_RX_PKT_2 |\ | ||
| 660 | ISR_RX_PKT_3) | ||
| 661 | |||
| 662 | #define ISR_OVER (\ | ||
| 663 | ISR_RFD0_UR |\ | ||
| 664 | ISR_RFD1_UR |\ | ||
| 665 | ISR_RFD2_UR |\ | ||
| 666 | ISR_RFD3_UR |\ | ||
| 667 | ISR_HW_RXF_OV |\ | ||
| 668 | ISR_TXF_UR) | ||
| 669 | |||
| 670 | #define ISR_ERROR (\ | ||
| 671 | ISR_DMAR_TO_RST |\ | ||
| 672 | ISR_TXQ_TO_RST |\ | ||
| 673 | ISR_DMAW_TO_RST |\ | ||
| 674 | ISR_PHY_LINKDOWN) | ||
| 675 | |||
| 676 | #define REG_INT_RETRIG_TIMER 0x1608 | ||
| 677 | #define INT_RETRIG_TIMER_MASK 0xFFFF | ||
| 678 | |||
| 679 | #define REG_HDS_CTRL 0x160C | ||
| 680 | #define HDS_CTRL_EN 0x0001 | ||
| 681 | #define HDS_CTRL_BACKFILLSIZE_SHIFT 8 | ||
| 682 | #define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF | ||
| 683 | #define HDS_CTRL_MAX_HDRSIZE_SHIFT 20 | ||
| 684 | #define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF | ||
| 685 | |||
| 686 | #define REG_MAC_RX_STATUS_BIN 0x1700 | ||
| 687 | #define REG_MAC_RX_STATUS_END 0x175c | ||
| 688 | #define REG_MAC_TX_STATUS_BIN 0x1760 | ||
| 689 | #define REG_MAC_TX_STATUS_END 0x17c0 | ||
| 690 | |||
| 691 | /* DEBUG ADDR */ | ||
| 692 | #define REG_DEBUG_DATA0 0x1900 | ||
| 693 | #define REG_DEBUG_DATA1 0x1904 | ||
| 694 | |||
| 695 | /* PHY Control Register */ | ||
| 696 | #define MII_BMCR 0x00 | ||
| 697 | #define BMCR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ | ||
| 698 | #define BMCR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ | ||
| 699 | #define BMCR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ | ||
| 700 | #define BMCR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ | ||
| 701 | #define BMCR_ISOLATE 0x0400 /* Isolate PHY from MII */ | ||
| 702 | #define BMCR_POWER_DOWN 0x0800 /* Power down */ | ||
| 703 | #define BMCR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ | ||
| 704 | #define BMCR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ | ||
| 705 | #define BMCR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ | ||
| 706 | #define BMCR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ | ||
| 707 | #define BMCR_SPEED_MASK 0x2040 | ||
| 708 | #define BMCR_SPEED_1000 0x0040 | ||
| 709 | #define BMCR_SPEED_100 0x2000 | ||
| 710 | #define BMCR_SPEED_10 0x0000 | ||
| 711 | |||
| 712 | /* PHY Status Register */ | ||
| 713 | #define MII_BMSR 0x01 | ||
| 714 | #define BMMSR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ | ||
| 715 | #define BMSR_JABBER_DETECT 0x0002 /* Jabber Detected */ | ||
| 716 | #define BMSR_LINK_STATUS 0x0004 /* Link Status 1 = link */ | ||
| 717 | #define BMSR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ | ||
| 718 | #define BMSR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ | ||
| 719 | #define BMSR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ | ||
| 720 | #define BMSR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ | ||
| 721 | #define BMSR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ | ||
| 722 | #define BMSR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ | ||
| 723 | #define BMSR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ | ||
| 724 | #define BMSR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ | ||
| 725 | #define BMSR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ | ||
| 726 | #define BMSR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ | ||
| 727 | #define BMMII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ | ||
| 728 | #define BMMII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ | ||
| 729 | |||
| 730 | #define MII_PHYSID1 0x02 | ||
| 731 | #define MII_PHYSID2 0x03 | ||
| 732 | |||
| 733 | /* Autoneg Advertisement Register */ | ||
| 734 | #define MII_ADVERTISE 0x04 | ||
| 735 | #define ADVERTISE_SPEED_MASK 0x01E0 | ||
| 736 | #define ADVERTISE_DEFAULT_CAP 0x0DE0 | ||
| 737 | |||
| 738 | /* 1000BASE-T Control Register */ | ||
| 739 | #define MII_GIGA_CR 0x09 | ||
| 740 | #define GIGA_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port 0=DTE device */ | ||
| 741 | |||
| 742 | #define GIGA_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master 0=Configure PHY as Slave */ | ||
| 743 | #define GIGA_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ | ||
| 744 | #define GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ | ||
| 745 | #define GIGA_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ | ||
| 746 | #define GIGA_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ | ||
| 747 | #define GIGA_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ | ||
| 748 | #define GIGA_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ | ||
| 749 | #define GIGA_CR_1000T_SPEED_MASK 0x0300 | ||
| 750 | #define GIGA_CR_1000T_DEFAULT_CAP 0x0300 | ||
| 751 | |||
| 752 | /* PHY Specific Status Register */ | ||
| 753 | #define MII_GIGA_PSSR 0x11 | ||
| 754 | #define GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ | ||
| 755 | #define GIGA_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ | ||
| 756 | #define GIGA_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ | ||
| 757 | #define GIGA_PSSR_10MBS 0x0000 /* 00=10Mbs */ | ||
| 758 | #define GIGA_PSSR_100MBS 0x4000 /* 01=100Mbs */ | ||
| 759 | #define GIGA_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ | ||
| 760 | |||
| 761 | /* PHY Interrupt Enable Register */ | ||
| 762 | #define MII_IER 0x12 | ||
| 763 | #define IER_LINK_UP 0x0400 | ||
| 764 | #define IER_LINK_DOWN 0x0800 | ||
| 765 | |||
| 766 | /* PHY Interrupt Status Register */ | ||
| 767 | #define MII_ISR 0x13 | ||
| 768 | #define ISR_LINK_UP 0x0400 | ||
| 769 | #define ISR_LINK_DOWN 0x0800 | ||
| 770 | |||
| 771 | /* Cable-Detect-Test Control Register */ | ||
| 772 | #define MII_CDTC 0x16 | ||
| 773 | #define CDTC_EN_OFF 0 /* sc */ | ||
| 774 | #define CDTC_EN_BITS 1 | ||
| 775 | #define CDTC_PAIR_OFF 8 | ||
| 776 | #define CDTC_PAIR_BIT 2 | ||
| 777 | |||
| 778 | /* Cable-Detect-Test Status Register */ | ||
| 779 | #define MII_CDTS 0x1C | ||
| 780 | #define CDTS_STATUS_OFF 8 | ||
| 781 | #define CDTS_STATUS_BITS 2 | ||
| 782 | #define CDTS_STATUS_NORMAL 0 | ||
| 783 | #define CDTS_STATUS_SHORT 1 | ||
| 784 | #define CDTS_STATUS_OPEN 2 | ||
| 785 | #define CDTS_STATUS_INVALID 3 | ||
| 786 | |||
| 787 | #define MII_DBG_ADDR 0x1D | ||
| 788 | #define MII_DBG_DATA 0x1E | ||
| 789 | |||
| 790 | #define MII_ANA_CTRL_0 0x0 | ||
| 791 | #define ANA_RESTART_CAL 0x0001 | ||
| 792 | #define ANA_MANUL_SWICH_ON_SHIFT 0x1 | ||
| 793 | #define ANA_MANUL_SWICH_ON_MASK 0xF | ||
| 794 | #define ANA_MAN_ENABLE 0x0020 | ||
| 795 | #define ANA_SEL_HSP 0x0040 | ||
| 796 | #define ANA_EN_HB 0x0080 | ||
| 797 | #define ANA_EN_HBIAS 0x0100 | ||
| 798 | #define ANA_OEN_125M 0x0200 | ||
| 799 | #define ANA_EN_LCKDT 0x0400 | ||
| 800 | #define ANA_LCKDT_PHY 0x0800 | ||
| 801 | #define ANA_AFE_MODE 0x1000 | ||
| 802 | #define ANA_VCO_SLOW 0x2000 | ||
| 803 | #define ANA_VCO_FAST 0x4000 | ||
| 804 | #define ANA_SEL_CLK125M_DSP 0x8000 | ||
| 805 | |||
| 806 | #define MII_ANA_CTRL_4 0x4 | ||
| 807 | #define ANA_IECHO_ADJ_MASK 0xF | ||
| 808 | #define ANA_IECHO_ADJ_3_SHIFT 0 | ||
| 809 | #define ANA_IECHO_ADJ_2_SHIFT 4 | ||
| 810 | #define ANA_IECHO_ADJ_1_SHIFT 8 | ||
| 811 | #define ANA_IECHO_ADJ_0_SHIFT 12 | ||
| 812 | |||
| 813 | #define MII_ANA_CTRL_5 0x5 | ||
| 814 | #define ANA_SERDES_CDR_BW_SHIFT 0 | ||
| 815 | #define ANA_SERDES_CDR_BW_MASK 0x3 | ||
| 816 | #define ANA_MS_PAD_DBG 0x0004 | ||
| 817 | #define ANA_SPEEDUP_DBG 0x0008 | ||
| 818 | #define ANA_SERDES_TH_LOS_SHIFT 4 | ||
| 819 | #define ANA_SERDES_TH_LOS_MASK 0x3 | ||
| 820 | #define ANA_SERDES_EN_DEEM 0x0040 | ||
| 821 | #define ANA_SERDES_TXELECIDLE 0x0080 | ||
| 822 | #define ANA_SERDES_BEACON 0x0100 | ||
| 823 | #define ANA_SERDES_HALFTXDR 0x0200 | ||
| 824 | #define ANA_SERDES_SEL_HSP 0x0400 | ||
| 825 | #define ANA_SERDES_EN_PLL 0x0800 | ||
| 826 | #define ANA_SERDES_EN 0x1000 | ||
| 827 | #define ANA_SERDES_EN_LCKDT 0x2000 | ||
| 828 | |||
| 829 | #define MII_ANA_CTRL_11 0xB | ||
| 830 | #define ANA_PS_HIB_EN 0x8000 | ||
| 831 | |||
| 832 | #define MII_ANA_CTRL_18 0x12 | ||
| 833 | #define ANA_TEST_MODE_10BT_01SHIFT 0 | ||
| 834 | #define ANA_TEST_MODE_10BT_01MASK 0x3 | ||
| 835 | #define ANA_LOOP_SEL_10BT 0x0004 | ||
| 836 | #define ANA_RGMII_MODE_SW 0x0008 | ||
| 837 | #define ANA_EN_LONGECABLE 0x0010 | ||
| 838 | #define ANA_TEST_MODE_10BT_2 0x0020 | ||
| 839 | #define ANA_EN_10BT_IDLE 0x0400 | ||
| 840 | #define ANA_EN_MASK_TB 0x0800 | ||
| 841 | #define ANA_TRIGGER_SEL_TIMER_SHIFT 12 | ||
| 842 | #define ANA_TRIGGER_SEL_TIMER_MASK 0x3 | ||
| 843 | #define ANA_INTERVAL_SEL_TIMER_SHIFT 14 | ||
| 844 | #define ANA_INTERVAL_SEL_TIMER_MASK 0x3 | ||
| 845 | |||
| 846 | #define MII_ANA_CTRL_41 0x29 | ||
| 847 | #define ANA_TOP_PS_EN 0x8000 | ||
| 848 | |||
| 849 | #define MII_ANA_CTRL_54 0x36 | ||
| 850 | #define ANA_LONG_CABLE_TH_100_SHIFT 0 | ||
| 851 | #define ANA_LONG_CABLE_TH_100_MASK 0x3F | ||
| 852 | #define ANA_DESERVED 0x0040 | ||
| 853 | #define ANA_EN_LIT_CH 0x0080 | ||
| 854 | #define ANA_SHORT_CABLE_TH_100_SHIFT 8 | ||
| 855 | #define ANA_SHORT_CABLE_TH_100_MASK 0x3F | ||
| 856 | #define ANA_BP_BAD_LINK_ACCUM 0x4000 | ||
| 857 | #define ANA_BP_SMALL_BW 0x8000 | ||
| 858 | |||
| 859 | #endif /*_ATL1C_HW_H_*/ | ||
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c new file mode 100644 index 00000000000..deb7b53167e --- /dev/null +++ b/drivers/net/atl1c/atl1c_main.c | |||
| @@ -0,0 +1,2797 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Derived from Intel e1000 driver | ||
| 5 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "atl1c.h" | ||
| 23 | |||
| 24 | #define ATL1C_DRV_VERSION "1.0.0.1-NAPI" | ||
| 25 | char atl1c_driver_name[] = "atl1c"; | ||
| 26 | char atl1c_driver_version[] = ATL1C_DRV_VERSION; | ||
| 27 | #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 | ||
| 28 | #define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 | ||
| 29 | /* | ||
| 30 | * atl1c_pci_tbl - PCI Device ID Table | ||
| 31 | * | ||
| 32 | * Wildcard entries (PCI_ANY_ID) should come last | ||
| 33 | * Last entry must be all 0s | ||
| 34 | * | ||
| 35 | * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, | ||
| 36 | * Class, Class Mask, private data (not used) } | ||
| 37 | */ | ||
| 38 | static struct pci_device_id atl1c_pci_tbl[] = { | ||
| 39 | {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, | ||
| 40 | {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, | ||
| 41 | /* required last entry */ | ||
| 42 | { 0 } | ||
| 43 | }; | ||
| 44 | MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); | ||
| 45 | |||
| 46 | MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>"); | ||
| 47 | MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); | ||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | MODULE_VERSION(ATL1C_DRV_VERSION); | ||
| 50 | |||
| 51 | static int atl1c_stop_mac(struct atl1c_hw *hw); | ||
| 52 | static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw); | ||
| 53 | static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw); | ||
| 54 | static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); | ||
| 55 | static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); | ||
| 56 | static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); | ||
| 57 | static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, | ||
| 58 | int *work_done, int work_to_do); | ||
| 59 | |||
| 60 | static const u16 atl1c_pay_load_size[] = { | ||
| 61 | 128, 256, 512, 1024, 2048, 4096, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] = | ||
| 65 | { | ||
| 66 | REG_MB_RFD0_PROD_IDX, | ||
| 67 | REG_MB_RFD1_PROD_IDX, | ||
| 68 | REG_MB_RFD2_PROD_IDX, | ||
| 69 | REG_MB_RFD3_PROD_IDX | ||
| 70 | }; | ||
| 71 | |||
| 72 | static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = | ||
| 73 | { | ||
| 74 | REG_RFD0_HEAD_ADDR_LO, | ||
| 75 | REG_RFD1_HEAD_ADDR_LO, | ||
| 76 | REG_RFD2_HEAD_ADDR_LO, | ||
| 77 | REG_RFD3_HEAD_ADDR_LO | ||
| 78 | }; | ||
| 79 | |||
| 80 | static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = | ||
| 81 | { | ||
| 82 | REG_RRD0_HEAD_ADDR_LO, | ||
| 83 | REG_RRD1_HEAD_ADDR_LO, | ||
| 84 | REG_RRD2_HEAD_ADDR_LO, | ||
| 85 | REG_RRD3_HEAD_ADDR_LO | ||
| 86 | }; | ||
| 87 | |||
| 88 | static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | | ||
| 89 | NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; | ||
| 90 | |||
| 91 | /* | ||
| 92 | * atl1c_init_pcie - init PCIE module | ||
| 93 | */ | ||
| 94 | static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) | ||
| 95 | { | ||
| 96 | u32 data; | ||
| 97 | u32 pci_cmd; | ||
| 98 | struct pci_dev *pdev = hw->adapter->pdev; | ||
| 99 | |||
| 100 | AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); | ||
| 101 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
| 102 | pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | ||
| 103 | PCI_COMMAND_IO); | ||
| 104 | AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd); | ||
| 105 | |||
| 106 | /* | ||
| 107 | * Clear any PowerSaveing Settings | ||
| 108 | */ | ||
| 109 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
| 110 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Mask some pcie error bits | ||
| 114 | */ | ||
| 115 | AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data); | ||
| 116 | data &= ~PCIE_UC_SERVRITY_DLP; | ||
| 117 | data &= ~PCIE_UC_SERVRITY_FCP; | ||
| 118 | AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data); | ||
| 119 | |||
| 120 | if (flag & ATL1C_PCIE_L0S_L1_DISABLE) | ||
| 121 | atl1c_disable_l0s_l1(hw); | ||
| 122 | if (flag & ATL1C_PCIE_PHY_RESET) | ||
| 123 | AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); | ||
| 124 | else | ||
| 125 | AT_WRITE_REG(hw, REG_GPHY_CTRL, | ||
| 126 | GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET); | ||
| 127 | |||
| 128 | msleep(1); | ||
| 129 | } | ||
| 130 | |||
| 131 | /* | ||
| 132 | * atl1c_irq_enable - Enable default interrupt generation settings | ||
| 133 | * @adapter: board private structure | ||
| 134 | */ | ||
| 135 | static inline void atl1c_irq_enable(struct atl1c_adapter *adapter) | ||
| 136 | { | ||
| 137 | if (likely(atomic_dec_and_test(&adapter->irq_sem))) { | ||
| 138 | AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF); | ||
| 139 | AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); | ||
| 140 | AT_WRITE_FLUSH(&adapter->hw); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | /* | ||
| 145 | * atl1c_irq_disable - Mask off interrupt generation on the NIC | ||
| 146 | * @adapter: board private structure | ||
| 147 | */ | ||
| 148 | static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) | ||
| 149 | { | ||
| 150 | atomic_inc(&adapter->irq_sem); | ||
| 151 | AT_WRITE_REG(&adapter->hw, REG_IMR, 0); | ||
| 152 | AT_WRITE_FLUSH(&adapter->hw); | ||
| 153 | synchronize_irq(adapter->pdev->irq); | ||
| 154 | } | ||
| 155 | |||
| 156 | /* | ||
| 157 | * atl1c_irq_reset - reset interrupt confiure on the NIC | ||
| 158 | * @adapter: board private structure | ||
| 159 | */ | ||
| 160 | static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) | ||
| 161 | { | ||
| 162 | atomic_set(&adapter->irq_sem, 1); | ||
| 163 | atl1c_irq_enable(adapter); | ||
| 164 | } | ||
| 165 | |||
| 166 | /* | ||
| 167 | * atl1c_phy_config - Timer Call-back | ||
| 168 | * @data: pointer to netdev cast into an unsigned long | ||
| 169 | */ | ||
| 170 | static void atl1c_phy_config(unsigned long data) | ||
| 171 | { | ||
| 172 | struct atl1c_adapter *adapter = (struct atl1c_adapter *) data; | ||
| 173 | struct atl1c_hw *hw = &adapter->hw; | ||
| 174 | unsigned long flags; | ||
| 175 | |||
| 176 | spin_lock_irqsave(&adapter->mdio_lock, flags); | ||
| 177 | atl1c_restart_autoneg(hw); | ||
| 178 | spin_unlock_irqrestore(&adapter->mdio_lock, flags); | ||
| 179 | } | ||
| 180 | |||
| 181 | void atl1c_reinit_locked(struct atl1c_adapter *adapter) | ||
| 182 | { | ||
| 183 | |||
| 184 | WARN_ON(in_interrupt()); | ||
| 185 | atl1c_down(adapter); | ||
| 186 | atl1c_up(adapter); | ||
| 187 | clear_bit(__AT_RESETTING, &adapter->flags); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void atl1c_reset_task(struct work_struct *work) | ||
| 191 | { | ||
| 192 | struct atl1c_adapter *adapter; | ||
| 193 | struct net_device *netdev; | ||
| 194 | |||
| 195 | adapter = container_of(work, struct atl1c_adapter, reset_task); | ||
| 196 | netdev = adapter->netdev; | ||
| 197 | |||
| 198 | netif_device_detach(netdev); | ||
| 199 | atl1c_down(adapter); | ||
| 200 | atl1c_up(adapter); | ||
| 201 | netif_device_attach(netdev); | ||
| 202 | } | ||
| 203 | |||
| 204 | static void atl1c_check_link_status(struct atl1c_adapter *adapter) | ||
| 205 | { | ||
| 206 | struct atl1c_hw *hw = &adapter->hw; | ||
| 207 | struct net_device *netdev = adapter->netdev; | ||
| 208 | struct pci_dev *pdev = adapter->pdev; | ||
| 209 | int err; | ||
| 210 | unsigned long flags; | ||
| 211 | u16 speed, duplex, phy_data; | ||
| 212 | |||
| 213 | spin_lock_irqsave(&adapter->mdio_lock, flags); | ||
| 214 | /* MII_BMSR must read twise */ | ||
| 215 | atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||
| 216 | atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||
| 217 | spin_unlock_irqrestore(&adapter->mdio_lock, flags); | ||
| 218 | |||
| 219 | if ((phy_data & BMSR_LSTATUS) == 0) { | ||
| 220 | /* link down */ | ||
| 221 | if (netif_carrier_ok(netdev)) { | ||
| 222 | hw->hibernate = true; | ||
| 223 | atl1c_set_aspm(hw, false); | ||
| 224 | if (atl1c_stop_mac(hw) != 0) | ||
| 225 | if (netif_msg_hw(adapter)) | ||
| 226 | dev_warn(&pdev->dev, | ||
| 227 | "stop mac failed\n"); | ||
| 228 | } | ||
| 229 | netif_carrier_off(netdev); | ||
| 230 | } else { | ||
| 231 | /* Link Up */ | ||
| 232 | hw->hibernate = false; | ||
| 233 | spin_lock_irqsave(&adapter->mdio_lock, flags); | ||
| 234 | err = atl1c_get_speed_and_duplex(hw, &speed, &duplex); | ||
| 235 | spin_unlock_irqrestore(&adapter->mdio_lock, flags); | ||
| 236 | if (unlikely(err)) | ||
| 237 | return; | ||
| 238 | /* link result is our setting */ | ||
| 239 | if (adapter->link_speed != speed || | ||
| 240 | adapter->link_duplex != duplex) { | ||
| 241 | adapter->link_speed = speed; | ||
| 242 | adapter->link_duplex = duplex; | ||
| 243 | atl1c_enable_tx_ctrl(hw); | ||
| 244 | atl1c_enable_rx_ctrl(hw); | ||
| 245 | atl1c_setup_mac_ctrl(adapter); | ||
| 246 | atl1c_set_aspm(hw, true); | ||
| 247 | if (netif_msg_link(adapter)) | ||
| 248 | dev_info(&pdev->dev, | ||
| 249 | "%s: %s NIC Link is Up<%d Mbps %s>\n", | ||
| 250 | atl1c_driver_name, netdev->name, | ||
| 251 | adapter->link_speed, | ||
| 252 | adapter->link_duplex == FULL_DUPLEX ? | ||
| 253 | "Full Duplex" : "Half Duplex"); | ||
| 254 | } | ||
| 255 | if (!netif_carrier_ok(netdev)) | ||
| 256 | netif_carrier_on(netdev); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | /* | ||
| 261 | * atl1c_link_chg_task - deal with link change event Out of interrupt context | ||
| 262 | * @netdev: network interface device structure | ||
| 263 | */ | ||
| 264 | static void atl1c_link_chg_task(struct work_struct *work) | ||
| 265 | { | ||
| 266 | struct atl1c_adapter *adapter; | ||
| 267 | |||
| 268 | adapter = container_of(work, struct atl1c_adapter, link_chg_task); | ||
| 269 | atl1c_check_link_status(adapter); | ||
| 270 | } | ||
| 271 | |||
| 272 | static void atl1c_link_chg_event(struct atl1c_adapter *adapter) | ||
| 273 | { | ||
| 274 | struct net_device *netdev = adapter->netdev; | ||
| 275 | struct pci_dev *pdev = adapter->pdev; | ||
| 276 | u16 phy_data; | ||
| 277 | u16 link_up; | ||
| 278 | |||
| 279 | spin_lock(&adapter->mdio_lock); | ||
| 280 | atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); | ||
| 281 | atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); | ||
| 282 | spin_unlock(&adapter->mdio_lock); | ||
| 283 | link_up = phy_data & BMSR_LSTATUS; | ||
| 284 | /* notify upper layer link down ASAP */ | ||
| 285 | if (!link_up) { | ||
| 286 | if (netif_carrier_ok(netdev)) { | ||
| 287 | /* old link state: Up */ | ||
| 288 | netif_carrier_off(netdev); | ||
| 289 | if (netif_msg_link(adapter)) | ||
| 290 | dev_info(&pdev->dev, | ||
| 291 | "%s: %s NIC Link is Down\n", | ||
| 292 | atl1c_driver_name, netdev->name); | ||
| 293 | adapter->link_speed = SPEED_0; | ||
| 294 | } | ||
| 295 | } | ||
| 296 | schedule_work(&adapter->link_chg_task); | ||
| 297 | } | ||
| 298 | |||
| 299 | static void atl1c_del_timer(struct atl1c_adapter *adapter) | ||
| 300 | { | ||
| 301 | del_timer_sync(&adapter->phy_config_timer); | ||
| 302 | } | ||
| 303 | |||
| 304 | static void atl1c_cancel_work(struct atl1c_adapter *adapter) | ||
| 305 | { | ||
| 306 | cancel_work_sync(&adapter->reset_task); | ||
| 307 | cancel_work_sync(&adapter->link_chg_task); | ||
| 308 | } | ||
| 309 | |||
| 310 | /* | ||
| 311 | * atl1c_tx_timeout - Respond to a Tx Hang | ||
| 312 | * @netdev: network interface device structure | ||
| 313 | */ | ||
| 314 | static void atl1c_tx_timeout(struct net_device *netdev) | ||
| 315 | { | ||
| 316 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 317 | |||
| 318 | /* Do the reset outside of interrupt context */ | ||
| 319 | schedule_work(&adapter->reset_task); | ||
| 320 | } | ||
| 321 | |||
| 322 | /* | ||
| 323 | * atl1c_set_multi - Multicast and Promiscuous mode set | ||
| 324 | * @netdev: network interface device structure | ||
| 325 | * | ||
| 326 | * The set_multi entry point is called whenever the multicast address | ||
| 327 | * list or the network interface flags are updated. This routine is | ||
| 328 | * responsible for configuring the hardware for proper multicast, | ||
| 329 | * promiscuous mode, and all-multi behavior. | ||
| 330 | */ | ||
| 331 | static void atl1c_set_multi(struct net_device *netdev) | ||
| 332 | { | ||
| 333 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 334 | struct atl1c_hw *hw = &adapter->hw; | ||
| 335 | struct dev_mc_list *mc_ptr; | ||
| 336 | u32 mac_ctrl_data; | ||
| 337 | u32 hash_value; | ||
| 338 | |||
| 339 | /* Check for Promiscuous and All Multicast modes */ | ||
| 340 | AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); | ||
| 341 | |||
| 342 | if (netdev->flags & IFF_PROMISC) { | ||
| 343 | mac_ctrl_data |= MAC_CTRL_PROMIS_EN; | ||
| 344 | } else if (netdev->flags & IFF_ALLMULTI) { | ||
| 345 | mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; | ||
| 346 | mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN; | ||
| 347 | } else { | ||
| 348 | mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); | ||
| 349 | } | ||
| 350 | |||
| 351 | AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); | ||
| 352 | |||
| 353 | /* clear the old settings from the multicast hash table */ | ||
| 354 | AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); | ||
| 355 | AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); | ||
| 356 | |||
| 357 | /* comoute mc addresses' hash value ,and put it into hash table */ | ||
| 358 | for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { | ||
| 359 | hash_value = atl1c_hash_mc_addr(hw, mc_ptr->dmi_addr); | ||
| 360 | atl1c_hash_set(hw, hash_value); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | static void atl1c_vlan_rx_register(struct net_device *netdev, | ||
| 365 | struct vlan_group *grp) | ||
| 366 | { | ||
| 367 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 368 | struct pci_dev *pdev = adapter->pdev; | ||
| 369 | u32 mac_ctrl_data = 0; | ||
| 370 | |||
| 371 | if (netif_msg_pktdata(adapter)) | ||
| 372 | dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n"); | ||
| 373 | |||
| 374 | atl1c_irq_disable(adapter); | ||
| 375 | |||
| 376 | adapter->vlgrp = grp; | ||
| 377 | AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data); | ||
| 378 | |||
| 379 | if (grp) { | ||
| 380 | /* enable VLAN tag insert/strip */ | ||
| 381 | mac_ctrl_data |= MAC_CTRL_RMV_VLAN; | ||
| 382 | } else { | ||
| 383 | /* disable VLAN tag insert/strip */ | ||
| 384 | mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; | ||
| 385 | } | ||
| 386 | |||
| 387 | AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); | ||
| 388 | atl1c_irq_enable(adapter); | ||
| 389 | } | ||
| 390 | |||
| 391 | static void atl1c_restore_vlan(struct atl1c_adapter *adapter) | ||
| 392 | { | ||
| 393 | struct pci_dev *pdev = adapter->pdev; | ||
| 394 | |||
| 395 | if (netif_msg_pktdata(adapter)) | ||
| 396 | dev_dbg(&pdev->dev, "atl1c_restore_vlan !"); | ||
| 397 | atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp); | ||
| 398 | } | ||
| 399 | /* | ||
| 400 | * atl1c_set_mac - Change the Ethernet Address of the NIC | ||
| 401 | * @netdev: network interface device structure | ||
| 402 | * @p: pointer to an address structure | ||
| 403 | * | ||
| 404 | * Returns 0 on success, negative on failure | ||
| 405 | */ | ||
| 406 | static int atl1c_set_mac_addr(struct net_device *netdev, void *p) | ||
| 407 | { | ||
| 408 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 409 | struct sockaddr *addr = p; | ||
| 410 | |||
| 411 | if (!is_valid_ether_addr(addr->sa_data)) | ||
| 412 | return -EADDRNOTAVAIL; | ||
| 413 | |||
| 414 | if (netif_running(netdev)) | ||
| 415 | return -EBUSY; | ||
| 416 | |||
| 417 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | ||
| 418 | memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); | ||
| 419 | |||
| 420 | atl1c_hw_set_mac_addr(&adapter->hw); | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, | ||
| 426 | struct net_device *dev) | ||
| 427 | { | ||
| 428 | int mtu = dev->mtu; | ||
| 429 | |||
| 430 | adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? | ||
| 431 | roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; | ||
| 432 | } | ||
| 433 | /* | ||
| 434 | * atl1c_change_mtu - Change the Maximum Transfer Unit | ||
| 435 | * @netdev: network interface device structure | ||
| 436 | * @new_mtu: new value for maximum frame size | ||
| 437 | * | ||
| 438 | * Returns 0 on success, negative on failure | ||
| 439 | */ | ||
| 440 | static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) | ||
| 441 | { | ||
| 442 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 443 | int old_mtu = netdev->mtu; | ||
| 444 | int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; | ||
| 445 | |||
| 446 | if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || | ||
| 447 | (max_frame > MAX_JUMBO_FRAME_SIZE)) { | ||
| 448 | if (netif_msg_link(adapter)) | ||
| 449 | dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); | ||
| 450 | return -EINVAL; | ||
| 451 | } | ||
| 452 | /* set MTU */ | ||
| 453 | if (old_mtu != new_mtu && netif_running(netdev)) { | ||
| 454 | while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) | ||
| 455 | msleep(1); | ||
| 456 | netdev->mtu = new_mtu; | ||
| 457 | adapter->hw.max_frame_size = new_mtu; | ||
| 458 | atl1c_set_rxbufsize(adapter, netdev); | ||
| 459 | atl1c_down(adapter); | ||
| 460 | atl1c_up(adapter); | ||
| 461 | clear_bit(__AT_RESETTING, &adapter->flags); | ||
| 462 | if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { | ||
| 463 | u32 phy_data; | ||
| 464 | |||
| 465 | AT_READ_REG(&adapter->hw, 0x1414, &phy_data); | ||
| 466 | phy_data |= 0x10000000; | ||
| 467 | AT_WRITE_REG(&adapter->hw, 0x1414, phy_data); | ||
| 468 | } | ||
| 469 | |||
| 470 | } | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* | ||
| 475 | * caller should hold mdio_lock | ||
| 476 | */ | ||
| 477 | static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) | ||
| 478 | { | ||
| 479 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 480 | u16 result; | ||
| 481 | |||
| 482 | atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); | ||
| 483 | return result; | ||
| 484 | } | ||
| 485 | |||
| 486 | static void atl1c_mdio_write(struct net_device *netdev, int phy_id, | ||
| 487 | int reg_num, int val) | ||
| 488 | { | ||
| 489 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 490 | |||
| 491 | atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); | ||
| 492 | } | ||
| 493 | |||
| 494 | /* | ||
| 495 | * atl1c_mii_ioctl - | ||
| 496 | * @netdev: | ||
| 497 | * @ifreq: | ||
| 498 | * @cmd: | ||
| 499 | */ | ||
| 500 | static int atl1c_mii_ioctl(struct net_device *netdev, | ||
| 501 | struct ifreq *ifr, int cmd) | ||
| 502 | { | ||
| 503 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 504 | struct pci_dev *pdev = adapter->pdev; | ||
| 505 | struct mii_ioctl_data *data = if_mii(ifr); | ||
| 506 | unsigned long flags; | ||
| 507 | int retval = 0; | ||
| 508 | |||
| 509 | if (!netif_running(netdev)) | ||
| 510 | return -EINVAL; | ||
| 511 | |||
| 512 | spin_lock_irqsave(&adapter->mdio_lock, flags); | ||
| 513 | switch (cmd) { | ||
| 514 | case SIOCGMIIPHY: | ||
| 515 | data->phy_id = 0; | ||
| 516 | break; | ||
| 517 | |||
| 518 | case SIOCGMIIREG: | ||
| 519 | if (!capable(CAP_NET_ADMIN)) { | ||
| 520 | retval = -EPERM; | ||
| 521 | goto out; | ||
| 522 | } | ||
| 523 | if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, | ||
| 524 | &data->val_out)) { | ||
| 525 | retval = -EIO; | ||
| 526 | goto out; | ||
| 527 | } | ||
| 528 | break; | ||
| 529 | |||
| 530 | case SIOCSMIIREG: | ||
| 531 | if (!capable(CAP_NET_ADMIN)) { | ||
| 532 | retval = -EPERM; | ||
| 533 | goto out; | ||
| 534 | } | ||
| 535 | if (data->reg_num & ~(0x1F)) { | ||
| 536 | retval = -EFAULT; | ||
| 537 | goto out; | ||
| 538 | } | ||
| 539 | |||
| 540 | dev_dbg(&pdev->dev, "<atl1c_mii_ioctl> write %x %x", | ||
| 541 | data->reg_num, data->val_in); | ||
| 542 | if (atl1c_write_phy_reg(&adapter->hw, | ||
| 543 | data->reg_num, data->val_in)) { | ||
| 544 | retval = -EIO; | ||
| 545 | goto out; | ||
| 546 | } | ||
| 547 | break; | ||
| 548 | |||
| 549 | default: | ||
| 550 | retval = -EOPNOTSUPP; | ||
| 551 | break; | ||
| 552 | } | ||
| 553 | out: | ||
| 554 | spin_unlock_irqrestore(&adapter->mdio_lock, flags); | ||
| 555 | return retval; | ||
| 556 | } | ||
| 557 | |||
| 558 | /* | ||
| 559 | * atl1c_ioctl - | ||
| 560 | * @netdev: | ||
| 561 | * @ifreq: | ||
| 562 | * @cmd: | ||
| 563 | */ | ||
| 564 | static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||
| 565 | { | ||
| 566 | switch (cmd) { | ||
| 567 | case SIOCGMIIPHY: | ||
| 568 | case SIOCGMIIREG: | ||
| 569 | case SIOCSMIIREG: | ||
| 570 | return atl1c_mii_ioctl(netdev, ifr, cmd); | ||
| 571 | default: | ||
| 572 | return -EOPNOTSUPP; | ||
| 573 | } | ||
| 574 | } | ||
| 575 | |||
| 576 | /* | ||
| 577 | * atl1c_alloc_queues - Allocate memory for all rings | ||
| 578 | * @adapter: board private structure to initialize | ||
| 579 | * | ||
| 580 | */ | ||
| 581 | static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter) | ||
| 582 | { | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 586 | static void atl1c_set_mac_type(struct atl1c_hw *hw) | ||
| 587 | { | ||
| 588 | switch (hw->device_id) { | ||
| 589 | case PCI_DEVICE_ID_ATTANSIC_L2C: | ||
| 590 | hw->nic_type = athr_l2c; | ||
| 591 | break; | ||
| 592 | |||
| 593 | case PCI_DEVICE_ID_ATTANSIC_L1C: | ||
| 594 | hw->nic_type = athr_l1c; | ||
| 595 | break; | ||
| 596 | |||
| 597 | default: | ||
| 598 | break; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | |||
| 602 | static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) | ||
| 603 | { | ||
| 604 | u32 phy_status_data; | ||
| 605 | u32 link_ctrl_data; | ||
| 606 | |||
| 607 | atl1c_set_mac_type(hw); | ||
| 608 | AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data); | ||
| 609 | AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); | ||
| 610 | |||
| 611 | hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ | | ||
| 612 | ATL1C_INTR_MODRT_ENABLE | | ||
| 613 | ATL1C_RX_IPV6_CHKSUM | | ||
| 614 | ATL1C_TXQ_MODE_ENHANCE; | ||
| 615 | if (link_ctrl_data & LINK_CTRL_L0S_EN) | ||
| 616 | hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; | ||
| 617 | if (link_ctrl_data & LINK_CTRL_L1_EN) | ||
| 618 | hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; | ||
| 619 | |||
| 620 | if (hw->nic_type == athr_l1c) { | ||
| 621 | hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; | ||
| 622 | hw->ctrl_flags |= ATL1C_LINK_CAP_1000M; | ||
| 623 | } | ||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | /* | ||
| 627 | * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) | ||
| 628 | * @adapter: board private structure to initialize | ||
| 629 | * | ||
| 630 | * atl1c_sw_init initializes the Adapter private data structure. | ||
| 631 | * Fields are initialized based on PCI device information and | ||
| 632 | * OS network device settings (MTU size). | ||
| 633 | */ | ||
| 634 | static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) | ||
| 635 | { | ||
| 636 | struct atl1c_hw *hw = &adapter->hw; | ||
| 637 | struct pci_dev *pdev = adapter->pdev; | ||
| 638 | |||
| 639 | adapter->wol = 0; | ||
| 640 | adapter->link_speed = SPEED_0; | ||
| 641 | adapter->link_duplex = FULL_DUPLEX; | ||
| 642 | adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE; | ||
| 643 | adapter->tpd_ring[0].count = 1024; | ||
| 644 | adapter->rfd_ring[0].count = 512; | ||
| 645 | |||
| 646 | hw->vendor_id = pdev->vendor; | ||
| 647 | hw->device_id = pdev->device; | ||
| 648 | hw->subsystem_vendor_id = pdev->subsystem_vendor; | ||
| 649 | hw->subsystem_id = pdev->subsystem_device; | ||
| 650 | |||
| 651 | /* before link up, we assume hibernate is true */ | ||
| 652 | hw->hibernate = true; | ||
| 653 | hw->media_type = MEDIA_TYPE_AUTO_SENSOR; | ||
| 654 | if (atl1c_setup_mac_funcs(hw) != 0) { | ||
| 655 | dev_err(&pdev->dev, "set mac function pointers failed\n"); | ||
| 656 | return -1; | ||
| 657 | } | ||
| 658 | hw->intr_mask = IMR_NORMAL_MASK; | ||
| 659 | hw->phy_configured = false; | ||
| 660 | hw->preamble_len = 7; | ||
| 661 | hw->max_frame_size = adapter->netdev->mtu; | ||
| 662 | if (adapter->num_rx_queues < 2) { | ||
| 663 | hw->rss_type = atl1c_rss_disable; | ||
| 664 | hw->rss_mode = atl1c_rss_mode_disable; | ||
| 665 | } else { | ||
| 666 | hw->rss_type = atl1c_rss_ipv4; | ||
| 667 | hw->rss_mode = atl1c_rss_mul_que_mul_int; | ||
| 668 | hw->rss_hash_bits = 16; | ||
| 669 | } | ||
| 670 | hw->autoneg_advertised = ADVERTISED_Autoneg; | ||
| 671 | hw->indirect_tab = 0xE4E4E4E4; | ||
| 672 | hw->base_cpu = 0; | ||
| 673 | |||
| 674 | hw->ict = 50000; /* 100ms */ | ||
| 675 | hw->smb_timer = 200000; /* 400ms */ | ||
| 676 | hw->cmb_tpd = 4; | ||
| 677 | hw->cmb_tx_timer = 1; /* 2 us */ | ||
| 678 | hw->rx_imt = 200; | ||
| 679 | hw->tx_imt = 1000; | ||
| 680 | |||
| 681 | hw->tpd_burst = 5; | ||
| 682 | hw->rfd_burst = 8; | ||
| 683 | hw->dma_order = atl1c_dma_ord_out; | ||
| 684 | hw->dmar_block = atl1c_dma_req_1024; | ||
| 685 | hw->dmaw_block = atl1c_dma_req_1024; | ||
| 686 | hw->dmar_dly_cnt = 15; | ||
| 687 | hw->dmaw_dly_cnt = 4; | ||
| 688 | |||
| 689 | if (atl1c_alloc_queues(adapter)) { | ||
| 690 | dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); | ||
| 691 | return -ENOMEM; | ||
| 692 | } | ||
| 693 | /* TODO */ | ||
| 694 | atl1c_set_rxbufsize(adapter, adapter->netdev); | ||
| 695 | atomic_set(&adapter->irq_sem, 1); | ||
| 696 | spin_lock_init(&adapter->mdio_lock); | ||
| 697 | spin_lock_init(&adapter->tx_lock); | ||
| 698 | set_bit(__AT_DOWN, &adapter->flags); | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | /* | ||
| 704 | * atl1c_clean_tx_ring - Free Tx-skb | ||
| 705 | * @adapter: board private structure | ||
| 706 | */ | ||
| 707 | static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, | ||
| 708 | enum atl1c_trans_queue type) | ||
| 709 | { | ||
| 710 | struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; | ||
| 711 | struct atl1c_buffer *buffer_info; | ||
| 712 | struct pci_dev *pdev = adapter->pdev; | ||
| 713 | u16 index, ring_count; | ||
| 714 | |||
| 715 | ring_count = tpd_ring->count; | ||
| 716 | for (index = 0; index < ring_count; index++) { | ||
| 717 | buffer_info = &tpd_ring->buffer_info[index]; | ||
| 718 | if (buffer_info->state == ATL1_BUFFER_FREE) | ||
| 719 | continue; | ||
| 720 | if (buffer_info->dma) | ||
| 721 | pci_unmap_single(pdev, buffer_info->dma, | ||
| 722 | buffer_info->length, | ||
| 723 | PCI_DMA_TODEVICE); | ||
| 724 | if (buffer_info->skb) | ||
| 725 | dev_kfree_skb(buffer_info->skb); | ||
| 726 | buffer_info->dma = 0; | ||
| 727 | buffer_info->skb = NULL; | ||
| 728 | buffer_info->state = ATL1_BUFFER_FREE; | ||
| 729 | } | ||
| 730 | |||
| 731 | /* Zero out Tx-buffers */ | ||
| 732 | memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * | ||
| 733 | ring_count); | ||
| 734 | atomic_set(&tpd_ring->next_to_clean, 0); | ||
| 735 | tpd_ring->next_to_use = 0; | ||
| 736 | } | ||
| 737 | |||
| 738 | /* | ||
| 739 | * atl1c_clean_rx_ring - Free rx-reservation skbs | ||
| 740 | * @adapter: board private structure | ||
| 741 | */ | ||
| 742 | static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) | ||
| 743 | { | ||
| 744 | struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; | ||
| 745 | struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; | ||
| 746 | struct atl1c_buffer *buffer_info; | ||
| 747 | struct pci_dev *pdev = adapter->pdev; | ||
| 748 | int i, j; | ||
| 749 | |||
| 750 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
| 751 | for (j = 0; j < rfd_ring[i].count; j++) { | ||
| 752 | buffer_info = &rfd_ring[i].buffer_info[j]; | ||
| 753 | if (buffer_info->state == ATL1_BUFFER_FREE) | ||
| 754 | continue; | ||
| 755 | if (buffer_info->dma) | ||
| 756 | pci_unmap_single(pdev, buffer_info->dma, | ||
| 757 | buffer_info->length, | ||
| 758 | PCI_DMA_FROMDEVICE); | ||
| 759 | if (buffer_info->skb) | ||
| 760 | dev_kfree_skb(buffer_info->skb); | ||
| 761 | buffer_info->state = ATL1_BUFFER_FREE; | ||
| 762 | buffer_info->skb = NULL; | ||
| 763 | } | ||
| 764 | /* zero out the descriptor ring */ | ||
| 765 | memset(rfd_ring[i].desc, 0, rfd_ring[i].size); | ||
| 766 | rfd_ring[i].next_to_clean = 0; | ||
| 767 | rfd_ring[i].next_to_use = 0; | ||
| 768 | rrd_ring[i].next_to_use = 0; | ||
| 769 | rrd_ring[i].next_to_clean = 0; | ||
| 770 | } | ||
| 771 | } | ||
| 772 | |||
| 773 | /* | ||
| 774 | * Read / Write Ptr Initialize: | ||
| 775 | */ | ||
| 776 | static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) | ||
| 777 | { | ||
| 778 | struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; | ||
| 779 | struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; | ||
| 780 | struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; | ||
| 781 | struct atl1c_buffer *buffer_info; | ||
| 782 | int i, j; | ||
| 783 | |||
| 784 | for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { | ||
| 785 | tpd_ring[i].next_to_use = 0; | ||
| 786 | atomic_set(&tpd_ring[i].next_to_clean, 0); | ||
| 787 | buffer_info = tpd_ring[i].buffer_info; | ||
| 788 | for (j = 0; j < tpd_ring->count; j++) | ||
| 789 | buffer_info[i].state = ATL1_BUFFER_FREE; | ||
| 790 | } | ||
| 791 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
| 792 | rfd_ring[i].next_to_use = 0; | ||
| 793 | rfd_ring[i].next_to_clean = 0; | ||
| 794 | rrd_ring[i].next_to_use = 0; | ||
| 795 | rrd_ring[i].next_to_clean = 0; | ||
| 796 | for (j = 0; j < rfd_ring[i].count; j++) { | ||
| 797 | buffer_info = &rfd_ring[i].buffer_info[j]; | ||
| 798 | buffer_info->state = ATL1_BUFFER_FREE; | ||
| 799 | } | ||
| 800 | } | ||
| 801 | } | ||
| 802 | |||
| 803 | /* | ||
| 804 | * atl1c_free_ring_resources - Free Tx / RX descriptor Resources | ||
| 805 | * @adapter: board private structure | ||
| 806 | * | ||
| 807 | * Free all transmit software resources | ||
| 808 | */ | ||
| 809 | static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) | ||
| 810 | { | ||
| 811 | struct pci_dev *pdev = adapter->pdev; | ||
| 812 | |||
| 813 | pci_free_consistent(pdev, adapter->ring_header.size, | ||
| 814 | adapter->ring_header.desc, | ||
| 815 | adapter->ring_header.dma); | ||
| 816 | adapter->ring_header.desc = NULL; | ||
| 817 | |||
| 818 | /* Note: just free tdp_ring.buffer_info, | ||
| 819 | * it contain rfd_ring.buffer_info, do not double free */ | ||
| 820 | if (adapter->tpd_ring[0].buffer_info) { | ||
| 821 | kfree(adapter->tpd_ring[0].buffer_info); | ||
| 822 | adapter->tpd_ring[0].buffer_info = NULL; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 826 | /* | ||
| 827 | * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources | ||
| 828 | * @adapter: board private structure | ||
| 829 | * | ||
| 830 | * Return 0 on success, negative on failure | ||
| 831 | */ | ||
| 832 | static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) | ||
| 833 | { | ||
| 834 | struct pci_dev *pdev = adapter->pdev; | ||
| 835 | struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; | ||
| 836 | struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; | ||
| 837 | struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; | ||
| 838 | struct atl1c_ring_header *ring_header = &adapter->ring_header; | ||
| 839 | int num_rx_queues = adapter->num_rx_queues; | ||
| 840 | int size; | ||
| 841 | int i; | ||
| 842 | int count = 0; | ||
| 843 | int rx_desc_count = 0; | ||
| 844 | u32 offset = 0; | ||
| 845 | |||
| 846 | rrd_ring[0].count = rfd_ring[0].count; | ||
| 847 | for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) | ||
| 848 | tpd_ring[i].count = tpd_ring[0].count; | ||
| 849 | |||
| 850 | for (i = 1; i < adapter->num_rx_queues; i++) | ||
| 851 | rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count; | ||
| 852 | |||
| 853 | /* 2 tpd queue, one high priority queue, | ||
| 854 | * another normal priority queue */ | ||
| 855 | size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + | ||
| 856 | rfd_ring->count * num_rx_queues); | ||
| 857 | tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); | ||
| 858 | if (unlikely(!tpd_ring->buffer_info)) { | ||
| 859 | dev_err(&pdev->dev, "kzalloc failed, size = %d\n", | ||
| 860 | size); | ||
| 861 | goto err_nomem; | ||
| 862 | } | ||
| 863 | for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { | ||
| 864 | tpd_ring[i].buffer_info = | ||
| 865 | (struct atl1c_buffer *) (tpd_ring->buffer_info + count); | ||
| 866 | count += tpd_ring[i].count; | ||
| 867 | } | ||
| 868 | |||
| 869 | for (i = 0; i < num_rx_queues; i++) { | ||
| 870 | rfd_ring[i].buffer_info = | ||
| 871 | (struct atl1c_buffer *) (tpd_ring->buffer_info + count); | ||
| 872 | count += rfd_ring[i].count; | ||
| 873 | rx_desc_count += rfd_ring[i].count; | ||
| 874 | } | ||
| 875 | /* | ||
| 876 | * real ring DMA buffer | ||
| 877 | * each ring/block may need up to 8 bytes for alignment, hence the | ||
| 878 | * additional bytes tacked onto the end. | ||
| 879 | */ | ||
| 880 | ring_header->size = size = | ||
| 881 | sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + | ||
| 882 | sizeof(struct atl1c_rx_free_desc) * rx_desc_count + | ||
| 883 | sizeof(struct atl1c_recv_ret_status) * rx_desc_count + | ||
| 884 | sizeof(struct atl1c_hw_stats) + | ||
| 885 | 8 * 4 + 8 * 2 * num_rx_queues; | ||
| 886 | |||
| 887 | ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, | ||
| 888 | &ring_header->dma); | ||
| 889 | if (unlikely(!ring_header->desc)) { | ||
| 890 | dev_err(&pdev->dev, "pci_alloc_consistend failed\n"); | ||
| 891 | goto err_nomem; | ||
| 892 | } | ||
| 893 | memset(ring_header->desc, 0, ring_header->size); | ||
| 894 | /* init TPD ring */ | ||
| 895 | |||
| 896 | tpd_ring[0].dma = roundup(ring_header->dma, 8); | ||
| 897 | offset = tpd_ring[0].dma - ring_header->dma; | ||
| 898 | for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { | ||
| 899 | tpd_ring[i].dma = ring_header->dma + offset; | ||
| 900 | tpd_ring[i].desc = (u8 *) ring_header->desc + offset; | ||
| 901 | tpd_ring[i].size = | ||
| 902 | sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count; | ||
| 903 | offset += roundup(tpd_ring[i].size, 8); | ||
| 904 | } | ||
| 905 | /* init RFD ring */ | ||
| 906 | for (i = 0; i < num_rx_queues; i++) { | ||
| 907 | rfd_ring[i].dma = ring_header->dma + offset; | ||
| 908 | rfd_ring[i].desc = (u8 *) ring_header->desc + offset; | ||
| 909 | rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) * | ||
| 910 | rfd_ring[i].count; | ||
| 911 | offset += roundup(rfd_ring[i].size, 8); | ||
| 912 | } | ||
| 913 | |||
| 914 | /* init RRD ring */ | ||
| 915 | for (i = 0; i < num_rx_queues; i++) { | ||
| 916 | rrd_ring[i].dma = ring_header->dma + offset; | ||
| 917 | rrd_ring[i].desc = (u8 *) ring_header->desc + offset; | ||
| 918 | rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) * | ||
| 919 | rrd_ring[i].count; | ||
| 920 | offset += roundup(rrd_ring[i].size, 8); | ||
| 921 | } | ||
| 922 | |||
| 923 | adapter->smb.dma = ring_header->dma + offset; | ||
| 924 | adapter->smb.smb = (u8 *)ring_header->desc + offset; | ||
| 925 | return 0; | ||
| 926 | |||
| 927 | err_nomem: | ||
| 928 | kfree(tpd_ring->buffer_info); | ||
| 929 | return -ENOMEM; | ||
| 930 | } | ||
| 931 | |||
| 932 | static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) | ||
| 933 | { | ||
| 934 | struct atl1c_hw *hw = &adapter->hw; | ||
| 935 | struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *) | ||
| 936 | adapter->rfd_ring; | ||
| 937 | struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *) | ||
| 938 | adapter->rrd_ring; | ||
| 939 | struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) | ||
| 940 | adapter->tpd_ring; | ||
| 941 | struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb; | ||
| 942 | struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb; | ||
| 943 | int i; | ||
| 944 | |||
| 945 | /* TPD */ | ||
| 946 | AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, | ||
| 947 | (u32)((tpd_ring[atl1c_trans_normal].dma & | ||
| 948 | AT_DMA_HI_ADDR_MASK) >> 32)); | ||
| 949 | /* just enable normal priority TX queue */ | ||
| 950 | AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO, | ||
| 951 | (u32)(tpd_ring[atl1c_trans_normal].dma & | ||
| 952 | AT_DMA_LO_ADDR_MASK)); | ||
| 953 | AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO, | ||
| 954 | (u32)(tpd_ring[atl1c_trans_high].dma & | ||
| 955 | AT_DMA_LO_ADDR_MASK)); | ||
| 956 | AT_WRITE_REG(hw, REG_TPD_RING_SIZE, | ||
| 957 | (u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK)); | ||
| 958 | |||
| 959 | |||
| 960 | /* RFD */ | ||
| 961 | AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, | ||
| 962 | (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32)); | ||
| 963 | for (i = 0; i < adapter->num_rx_queues; i++) | ||
| 964 | AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i], | ||
| 965 | (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); | ||
| 966 | |||
| 967 | AT_WRITE_REG(hw, REG_RFD_RING_SIZE, | ||
| 968 | rfd_ring[0].count & RFD_RING_SIZE_MASK); | ||
| 969 | AT_WRITE_REG(hw, REG_RX_BUF_SIZE, | ||
| 970 | adapter->rx_buffer_len & RX_BUF_SIZE_MASK); | ||
| 971 | |||
| 972 | /* RRD */ | ||
| 973 | for (i = 0; i < adapter->num_rx_queues; i++) | ||
| 974 | AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i], | ||
| 975 | (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); | ||
| 976 | AT_WRITE_REG(hw, REG_RRD_RING_SIZE, | ||
| 977 | (rrd_ring[0].count & RRD_RING_SIZE_MASK)); | ||
| 978 | |||
| 979 | /* CMB */ | ||
| 980 | AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK); | ||
| 981 | |||
| 982 | /* SMB */ | ||
| 983 | AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI, | ||
| 984 | (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32)); | ||
| 985 | AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO, | ||
| 986 | (u32)(smb->dma & AT_DMA_LO_ADDR_MASK)); | ||
| 987 | /* Load all of base address above */ | ||
| 988 | AT_WRITE_REG(hw, REG_LOAD_PTR, 1); | ||
| 989 | } | ||
| 990 | |||
| 991 | static void atl1c_configure_tx(struct atl1c_adapter *adapter) | ||
| 992 | { | ||
| 993 | struct atl1c_hw *hw = &adapter->hw; | ||
| 994 | u32 dev_ctrl_data; | ||
| 995 | u32 max_pay_load; | ||
| 996 | u16 tx_offload_thresh; | ||
| 997 | u32 txq_ctrl_data; | ||
| 998 | u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */ | ||
| 999 | |||
| 1000 | extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; | ||
| 1001 | tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; | ||
| 1002 | AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, | ||
| 1003 | (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); | ||
| 1004 | AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data); | ||
| 1005 | max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) & | ||
| 1006 | DEVICE_CTRL_MAX_PAYLOAD_MASK; | ||
| 1007 | hw->dmaw_block = min(max_pay_load, hw->dmaw_block); | ||
| 1008 | max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) & | ||
| 1009 | DEVICE_CTRL_MAX_RREQ_SZ_MASK; | ||
| 1010 | hw->dmar_block = min(max_pay_load, hw->dmar_block); | ||
| 1011 | |||
| 1012 | txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) << | ||
| 1013 | TXQ_NUM_TPD_BURST_SHIFT; | ||
| 1014 | if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE) | ||
| 1015 | txq_ctrl_data |= TXQ_CTRL_ENH_MODE; | ||
| 1016 | txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] & | ||
| 1017 | TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT; | ||
| 1018 | |||
| 1019 | AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static void atl1c_configure_rx(struct atl1c_adapter *adapter) | ||
| 1023 | { | ||
| 1024 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1025 | u32 rxq_ctrl_data; | ||
| 1026 | |||
| 1027 | rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) << | ||
| 1028 | RXQ_RFD_BURST_NUM_SHIFT; | ||
| 1029 | |||
| 1030 | if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) | ||
| 1031 | rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; | ||
| 1032 | if (hw->rss_type == atl1c_rss_ipv4) | ||
| 1033 | rxq_ctrl_data |= RSS_HASH_IPV4; | ||
| 1034 | if (hw->rss_type == atl1c_rss_ipv4_tcp) | ||
| 1035 | rxq_ctrl_data |= RSS_HASH_IPV4_TCP; | ||
| 1036 | if (hw->rss_type == atl1c_rss_ipv6) | ||
| 1037 | rxq_ctrl_data |= RSS_HASH_IPV6; | ||
| 1038 | if (hw->rss_type == atl1c_rss_ipv6_tcp) | ||
| 1039 | rxq_ctrl_data |= RSS_HASH_IPV6_TCP; | ||
| 1040 | if (hw->rss_type != atl1c_rss_disable) | ||
| 1041 | rxq_ctrl_data |= RRS_HASH_CTRL_EN; | ||
| 1042 | |||
| 1043 | rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) << | ||
| 1044 | RSS_MODE_SHIFT; | ||
| 1045 | rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) << | ||
| 1046 | RSS_HASH_BITS_SHIFT; | ||
| 1047 | if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON) | ||
| 1048 | rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M & | ||
| 1049 | ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT; | ||
| 1050 | |||
| 1051 | AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static void atl1c_configure_rss(struct atl1c_adapter *adapter) | ||
| 1055 | { | ||
| 1056 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1057 | |||
| 1058 | AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); | ||
| 1059 | AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | static void atl1c_configure_dma(struct atl1c_adapter *adapter) | ||
| 1063 | { | ||
| 1064 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1065 | u32 dma_ctrl_data; | ||
| 1066 | |||
| 1067 | dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI; | ||
| 1068 | if (hw->ctrl_flags & ATL1C_CMB_ENABLE) | ||
| 1069 | dma_ctrl_data |= DMA_CTRL_CMB_EN; | ||
| 1070 | if (hw->ctrl_flags & ATL1C_SMB_ENABLE) | ||
| 1071 | dma_ctrl_data |= DMA_CTRL_SMB_EN; | ||
| 1072 | else | ||
| 1073 | dma_ctrl_data |= MAC_CTRL_SMB_DIS; | ||
| 1074 | |||
| 1075 | switch (hw->dma_order) { | ||
| 1076 | case atl1c_dma_ord_in: | ||
| 1077 | dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER; | ||
| 1078 | break; | ||
| 1079 | case atl1c_dma_ord_enh: | ||
| 1080 | dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER; | ||
| 1081 | break; | ||
| 1082 | case atl1c_dma_ord_out: | ||
| 1083 | dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER; | ||
| 1084 | break; | ||
| 1085 | default: | ||
| 1086 | break; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) | ||
| 1090 | << DMA_CTRL_DMAR_BURST_LEN_SHIFT; | ||
| 1091 | dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) | ||
| 1092 | << DMA_CTRL_DMAW_BURST_LEN_SHIFT; | ||
| 1093 | dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) | ||
| 1094 | << DMA_CTRL_DMAR_DLY_CNT_SHIFT; | ||
| 1095 | dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) | ||
| 1096 | << DMA_CTRL_DMAW_DLY_CNT_SHIFT; | ||
| 1097 | |||
| 1098 | AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | /* | ||
| 1102 | * Stop the mac, transmit and receive units | ||
| 1103 | * hw - Struct containing variables accessed by shared code | ||
| 1104 | * return : 0 or idle status (if error) | ||
| 1105 | */ | ||
| 1106 | static int atl1c_stop_mac(struct atl1c_hw *hw) | ||
| 1107 | { | ||
| 1108 | u32 data; | ||
| 1109 | int timeout; | ||
| 1110 | |||
| 1111 | AT_READ_REG(hw, REG_RXQ_CTRL, &data); | ||
| 1112 | data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN | | ||
| 1113 | RXQ3_CTRL_EN | RXQ_CTRL_EN); | ||
| 1114 | AT_WRITE_REG(hw, REG_RXQ_CTRL, data); | ||
| 1115 | |||
| 1116 | AT_READ_REG(hw, REG_TXQ_CTRL, &data); | ||
| 1117 | data &= ~TXQ_CTRL_EN; | ||
| 1118 | AT_WRITE_REG(hw, REG_TWSI_CTRL, data); | ||
| 1119 | |||
| 1120 | for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { | ||
| 1121 | AT_READ_REG(hw, REG_IDLE_STATUS, &data); | ||
| 1122 | if ((data & (IDLE_STATUS_RXQ_NO_IDLE | | ||
| 1123 | IDLE_STATUS_TXQ_NO_IDLE)) == 0) | ||
| 1124 | break; | ||
| 1125 | msleep(1); | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | AT_READ_REG(hw, REG_MAC_CTRL, &data); | ||
| 1129 | data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); | ||
| 1130 | AT_WRITE_REG(hw, REG_MAC_CTRL, data); | ||
| 1131 | |||
| 1132 | for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { | ||
| 1133 | AT_READ_REG(hw, REG_IDLE_STATUS, &data); | ||
| 1134 | if ((data & IDLE_STATUS_MASK) == 0) | ||
| 1135 | return 0; | ||
| 1136 | msleep(1); | ||
| 1137 | } | ||
| 1138 | return data; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) | ||
| 1142 | { | ||
| 1143 | u32 data; | ||
| 1144 | |||
| 1145 | AT_READ_REG(hw, REG_RXQ_CTRL, &data); | ||
| 1146 | switch (hw->adapter->num_rx_queues) { | ||
| 1147 | case 4: | ||
| 1148 | data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN); | ||
| 1149 | break; | ||
| 1150 | case 3: | ||
| 1151 | data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN); | ||
| 1152 | break; | ||
| 1153 | case 2: | ||
| 1154 | data |= RXQ1_CTRL_EN; | ||
| 1155 | break; | ||
| 1156 | default: | ||
| 1157 | break; | ||
| 1158 | } | ||
| 1159 | data |= RXQ_CTRL_EN; | ||
| 1160 | AT_WRITE_REG(hw, REG_RXQ_CTRL, data); | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw) | ||
| 1164 | { | ||
| 1165 | u32 data; | ||
| 1166 | |||
| 1167 | AT_READ_REG(hw, REG_TXQ_CTRL, &data); | ||
| 1168 | data |= TXQ_CTRL_EN; | ||
| 1169 | AT_WRITE_REG(hw, REG_TXQ_CTRL, data); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | /* | ||
| 1173 | * Reset the transmit and receive units; mask and clear all interrupts. | ||
| 1174 | * hw - Struct containing variables accessed by shared code | ||
| 1175 | * return : 0 or idle status (if error) | ||
| 1176 | */ | ||
| 1177 | static int atl1c_reset_mac(struct atl1c_hw *hw) | ||
| 1178 | { | ||
| 1179 | struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; | ||
| 1180 | struct pci_dev *pdev = adapter->pdev; | ||
| 1181 | u32 idle_status_data = 0; | ||
| 1182 | int timeout = 0; | ||
| 1183 | int ret; | ||
| 1184 | |||
| 1185 | AT_WRITE_REG(hw, REG_IMR, 0); | ||
| 1186 | AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); | ||
| 1187 | |||
| 1188 | ret = atl1c_stop_mac(hw); | ||
| 1189 | if (ret) | ||
| 1190 | return ret; | ||
| 1191 | /* | ||
| 1192 | * Issue Soft Reset to the MAC. This will reset the chip's | ||
| 1193 | * transmit, receive, DMA. It will not effect | ||
| 1194 | * the current PCI configuration. The global reset bit is self- | ||
| 1195 | * clearing, and should clear within a microsecond. | ||
| 1196 | */ | ||
| 1197 | AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); | ||
| 1198 | AT_WRITE_FLUSH(hw); | ||
| 1199 | msleep(10); | ||
| 1200 | /* Wait at least 10ms for All module to be Idle */ | ||
| 1201 | for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { | ||
| 1202 | AT_READ_REG(hw, REG_IDLE_STATUS, &idle_status_data); | ||
| 1203 | if ((idle_status_data & IDLE_STATUS_MASK) == 0) | ||
| 1204 | break; | ||
| 1205 | msleep(1); | ||
| 1206 | } | ||
| 1207 | if (timeout >= AT_HW_MAX_IDLE_DELAY) { | ||
| 1208 | dev_err(&pdev->dev, | ||
| 1209 | "MAC state machine cann't be idle since" | ||
| 1210 | " disabled for 10ms second\n"); | ||
| 1211 | return -1; | ||
| 1212 | } | ||
| 1213 | return 0; | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) | ||
| 1217 | { | ||
| 1218 | u32 pm_ctrl_data; | ||
| 1219 | |||
| 1220 | AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); | ||
| 1221 | pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << | ||
| 1222 | PM_CTRL_L1_ENTRY_TIMER_SHIFT); | ||
| 1223 | pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; | ||
| 1224 | pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; | ||
| 1225 | pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; | ||
| 1226 | pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK; | ||
| 1227 | pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; | ||
| 1228 | |||
| 1229 | pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; | ||
| 1230 | pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; | ||
| 1231 | pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; | ||
| 1232 | AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | /* | ||
| 1236 | * Set ASPM state. | ||
| 1237 | * Enable/disable L0s/L1 depend on link state. | ||
| 1238 | */ | ||
| 1239 | static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) | ||
| 1240 | { | ||
| 1241 | u32 pm_ctrl_data; | ||
| 1242 | |||
| 1243 | AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); | ||
| 1244 | |||
| 1245 | pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1; | ||
| 1246 | pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; | ||
| 1247 | pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN; | ||
| 1248 | pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << | ||
| 1249 | PM_CTRL_L1_ENTRY_TIMER_SHIFT); | ||
| 1250 | |||
| 1251 | pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; | ||
| 1252 | |||
| 1253 | if (linkup) { | ||
| 1254 | pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; | ||
| 1255 | pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; | ||
| 1256 | |||
| 1257 | if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) { | ||
| 1258 | pm_ctrl_data |= AT_ASPM_L1_TIMER << | ||
| 1259 | PM_CTRL_L1_ENTRY_TIMER_SHIFT; | ||
| 1260 | pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; | ||
| 1261 | } else | ||
| 1262 | pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; | ||
| 1263 | |||
| 1264 | if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) | ||
| 1265 | pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; | ||
| 1266 | else | ||
| 1267 | pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; | ||
| 1268 | |||
| 1269 | } else { | ||
| 1270 | pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; | ||
| 1271 | pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; | ||
| 1272 | |||
| 1273 | pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; | ||
| 1274 | |||
| 1275 | if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) | ||
| 1276 | pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; | ||
| 1277 | else | ||
| 1278 | pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) | ||
| 1285 | { | ||
| 1286 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1287 | struct net_device *netdev = adapter->netdev; | ||
| 1288 | u32 mac_ctrl_data; | ||
| 1289 | |||
| 1290 | mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; | ||
| 1291 | mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); | ||
| 1292 | |||
| 1293 | if (adapter->link_duplex == FULL_DUPLEX) { | ||
| 1294 | hw->mac_duplex = true; | ||
| 1295 | mac_ctrl_data |= MAC_CTRL_DUPLX; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | if (adapter->link_speed == SPEED_1000) | ||
| 1299 | hw->mac_speed = atl1c_mac_speed_1000; | ||
| 1300 | else | ||
| 1301 | hw->mac_speed = atl1c_mac_speed_10_100; | ||
| 1302 | |||
| 1303 | mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) << | ||
| 1304 | MAC_CTRL_SPEED_SHIFT; | ||
| 1305 | |||
| 1306 | mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); | ||
| 1307 | mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) << | ||
| 1308 | MAC_CTRL_PRMLEN_SHIFT); | ||
| 1309 | |||
| 1310 | if (adapter->vlgrp) | ||
| 1311 | mac_ctrl_data |= MAC_CTRL_RMV_VLAN; | ||
| 1312 | |||
| 1313 | mac_ctrl_data |= MAC_CTRL_BC_EN; | ||
| 1314 | if (netdev->flags & IFF_PROMISC) | ||
| 1315 | mac_ctrl_data |= MAC_CTRL_PROMIS_EN; | ||
| 1316 | if (netdev->flags & IFF_ALLMULTI) | ||
| 1317 | mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; | ||
| 1318 | |||
| 1319 | mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; | ||
| 1320 | AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | /* | ||
| 1324 | * atl1c_configure - Configure Transmit&Receive Unit after Reset | ||
| 1325 | * @adapter: board private structure | ||
| 1326 | * | ||
| 1327 | * Configure the Tx /Rx unit of the MAC after a reset. | ||
| 1328 | */ | ||
| 1329 | static int atl1c_configure(struct atl1c_adapter *adapter) | ||
| 1330 | { | ||
| 1331 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1332 | u32 master_ctrl_data = 0; | ||
| 1333 | u32 intr_modrt_data; | ||
| 1334 | |||
| 1335 | /* clear interrupt status */ | ||
| 1336 | AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); | ||
| 1337 | /* Clear any WOL status */ | ||
| 1338 | AT_WRITE_REG(hw, REG_WOL_CTRL, 0); | ||
| 1339 | /* set Interrupt Clear Timer | ||
| 1340 | * HW will enable self to assert interrupt event to system after | ||
| 1341 | * waiting x-time for software to notify it accept interrupt. | ||
| 1342 | */ | ||
| 1343 | AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER, | ||
| 1344 | hw->ict & INT_RETRIG_TIMER_MASK); | ||
| 1345 | |||
| 1346 | atl1c_configure_des_ring(adapter); | ||
| 1347 | |||
| 1348 | if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) { | ||
| 1349 | intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) << | ||
| 1350 | IRQ_MODRT_TX_TIMER_SHIFT; | ||
| 1351 | intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) << | ||
| 1352 | IRQ_MODRT_RX_TIMER_SHIFT; | ||
| 1353 | AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); | ||
| 1354 | master_ctrl_data |= | ||
| 1355 | MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ) | ||
| 1359 | master_ctrl_data |= MASTER_CTRL_INT_RDCLR; | ||
| 1360 | |||
| 1361 | AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); | ||
| 1362 | |||
| 1363 | if (hw->ctrl_flags & ATL1C_CMB_ENABLE) { | ||
| 1364 | AT_WRITE_REG(hw, REG_CMB_TPD_THRESH, | ||
| 1365 | hw->cmb_tpd & CMB_TPD_THRESH_MASK); | ||
| 1366 | AT_WRITE_REG(hw, REG_CMB_TX_TIMER, | ||
| 1367 | hw->cmb_tx_timer & CMB_TX_TIMER_MASK); | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | if (hw->ctrl_flags & ATL1C_SMB_ENABLE) | ||
| 1371 | AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, | ||
| 1372 | hw->smb_timer & SMB_STAT_TIMER_MASK); | ||
| 1373 | /* set MTU */ | ||
| 1374 | AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + | ||
| 1375 | VLAN_HLEN + ETH_FCS_LEN); | ||
| 1376 | /* HDS, disable */ | ||
| 1377 | AT_WRITE_REG(hw, REG_HDS_CTRL, 0); | ||
| 1378 | |||
| 1379 | atl1c_configure_tx(adapter); | ||
| 1380 | atl1c_configure_rx(adapter); | ||
| 1381 | atl1c_configure_rss(adapter); | ||
| 1382 | atl1c_configure_dma(adapter); | ||
| 1383 | |||
| 1384 | return 0; | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) | ||
| 1388 | { | ||
| 1389 | u16 hw_reg_addr = 0; | ||
| 1390 | unsigned long *stats_item = NULL; | ||
| 1391 | u32 data; | ||
| 1392 | |||
| 1393 | /* update rx status */ | ||
| 1394 | hw_reg_addr = REG_MAC_RX_STATUS_BIN; | ||
| 1395 | stats_item = &adapter->hw_stats.rx_ok; | ||
| 1396 | while (hw_reg_addr <= REG_MAC_RX_STATUS_END) { | ||
| 1397 | AT_READ_REG(&adapter->hw, hw_reg_addr, &data); | ||
| 1398 | *stats_item += data; | ||
| 1399 | stats_item++; | ||
| 1400 | hw_reg_addr += 4; | ||
| 1401 | } | ||
| 1402 | /* update tx status */ | ||
| 1403 | hw_reg_addr = REG_MAC_TX_STATUS_BIN; | ||
| 1404 | stats_item = &adapter->hw_stats.tx_ok; | ||
| 1405 | while (hw_reg_addr <= REG_MAC_TX_STATUS_END) { | ||
| 1406 | AT_READ_REG(&adapter->hw, hw_reg_addr, &data); | ||
| 1407 | *stats_item += data; | ||
| 1408 | stats_item++; | ||
| 1409 | hw_reg_addr += 4; | ||
| 1410 | } | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | /* | ||
| 1414 | * atl1c_get_stats - Get System Network Statistics | ||
| 1415 | * @netdev: network interface device structure | ||
| 1416 | * | ||
| 1417 | * Returns the address of the device statistics structure. | ||
| 1418 | * The statistics are actually updated from the timer callback. | ||
| 1419 | */ | ||
| 1420 | static struct net_device_stats *atl1c_get_stats(struct net_device *netdev) | ||
| 1421 | { | ||
| 1422 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 1423 | struct atl1c_hw_stats *hw_stats = &adapter->hw_stats; | ||
| 1424 | struct net_device_stats *net_stats = &adapter->net_stats; | ||
| 1425 | |||
| 1426 | atl1c_update_hw_stats(adapter); | ||
| 1427 | net_stats->rx_packets = hw_stats->rx_ok; | ||
| 1428 | net_stats->tx_packets = hw_stats->tx_ok; | ||
| 1429 | net_stats->rx_bytes = hw_stats->rx_byte_cnt; | ||
| 1430 | net_stats->tx_bytes = hw_stats->tx_byte_cnt; | ||
| 1431 | net_stats->multicast = hw_stats->rx_mcast; | ||
| 1432 | net_stats->collisions = hw_stats->tx_1_col + | ||
| 1433 | hw_stats->tx_2_col * 2 + | ||
| 1434 | hw_stats->tx_late_col + hw_stats->tx_abort_col; | ||
| 1435 | net_stats->rx_errors = hw_stats->rx_frag + hw_stats->rx_fcs_err + | ||
| 1436 | hw_stats->rx_len_err + hw_stats->rx_sz_ov + | ||
| 1437 | hw_stats->rx_rrd_ov + hw_stats->rx_align_err; | ||
| 1438 | net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov; | ||
| 1439 | net_stats->rx_length_errors = hw_stats->rx_len_err; | ||
| 1440 | net_stats->rx_crc_errors = hw_stats->rx_fcs_err; | ||
| 1441 | net_stats->rx_frame_errors = hw_stats->rx_align_err; | ||
| 1442 | net_stats->rx_over_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; | ||
| 1443 | |||
| 1444 | net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; | ||
| 1445 | |||
| 1446 | net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col + | ||
| 1447 | hw_stats->tx_underrun + hw_stats->tx_trunc; | ||
| 1448 | net_stats->tx_fifo_errors = hw_stats->tx_underrun; | ||
| 1449 | net_stats->tx_aborted_errors = hw_stats->tx_abort_col; | ||
| 1450 | net_stats->tx_window_errors = hw_stats->tx_late_col; | ||
| 1451 | |||
| 1452 | return &adapter->net_stats; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter) | ||
| 1456 | { | ||
| 1457 | u16 phy_data; | ||
| 1458 | |||
| 1459 | spin_lock(&adapter->mdio_lock); | ||
| 1460 | atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data); | ||
| 1461 | spin_unlock(&adapter->mdio_lock); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, | ||
| 1465 | enum atl1c_trans_queue type) | ||
| 1466 | { | ||
| 1467 | struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) | ||
| 1468 | &adapter->tpd_ring[type]; | ||
| 1469 | struct atl1c_buffer *buffer_info; | ||
| 1470 | u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); | ||
| 1471 | u16 hw_next_to_clean; | ||
| 1472 | u16 shift; | ||
| 1473 | u32 data; | ||
| 1474 | |||
| 1475 | if (type == atl1c_trans_high) | ||
| 1476 | shift = MB_HTPD_CONS_IDX_SHIFT; | ||
| 1477 | else | ||
| 1478 | shift = MB_NTPD_CONS_IDX_SHIFT; | ||
| 1479 | |||
| 1480 | AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data); | ||
| 1481 | hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK; | ||
| 1482 | |||
| 1483 | while (next_to_clean != hw_next_to_clean) { | ||
| 1484 | buffer_info = &tpd_ring->buffer_info[next_to_clean]; | ||
| 1485 | if (buffer_info->state == ATL1_BUFFER_BUSY) { | ||
| 1486 | pci_unmap_page(adapter->pdev, buffer_info->dma, | ||
| 1487 | buffer_info->length, PCI_DMA_TODEVICE); | ||
| 1488 | buffer_info->dma = 0; | ||
| 1489 | if (buffer_info->skb) { | ||
| 1490 | dev_kfree_skb_irq(buffer_info->skb); | ||
| 1491 | buffer_info->skb = NULL; | ||
| 1492 | } | ||
| 1493 | buffer_info->state = ATL1_BUFFER_FREE; | ||
| 1494 | } | ||
| 1495 | if (++next_to_clean == tpd_ring->count) | ||
| 1496 | next_to_clean = 0; | ||
| 1497 | atomic_set(&tpd_ring->next_to_clean, next_to_clean); | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | if (netif_queue_stopped(adapter->netdev) && | ||
| 1501 | netif_carrier_ok(adapter->netdev)) { | ||
| 1502 | netif_wake_queue(adapter->netdev); | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | return true; | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | /* | ||
| 1509 | * atl1c_intr - Interrupt Handler | ||
| 1510 | * @irq: interrupt number | ||
| 1511 | * @data: pointer to a network interface device structure | ||
| 1512 | * @pt_regs: CPU registers structure | ||
| 1513 | */ | ||
| 1514 | static irqreturn_t atl1c_intr(int irq, void *data) | ||
| 1515 | { | ||
| 1516 | struct net_device *netdev = data; | ||
| 1517 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 1518 | struct pci_dev *pdev = adapter->pdev; | ||
| 1519 | struct atl1c_hw *hw = &adapter->hw; | ||
| 1520 | int max_ints = AT_MAX_INT_WORK; | ||
| 1521 | int handled = IRQ_NONE; | ||
| 1522 | u32 status; | ||
| 1523 | u32 reg_data; | ||
| 1524 | |||
| 1525 | do { | ||
| 1526 | AT_READ_REG(hw, REG_ISR, ®_data); | ||
| 1527 | status = reg_data & hw->intr_mask; | ||
| 1528 | |||
| 1529 | if (status == 0 || (status & ISR_DIS_INT) != 0) { | ||
| 1530 | if (max_ints != AT_MAX_INT_WORK) | ||
| 1531 | handled = IRQ_HANDLED; | ||
| 1532 | break; | ||
| 1533 | } | ||
| 1534 | /* link event */ | ||
| 1535 | if (status & ISR_GPHY) | ||
| 1536 | atl1c_clear_phy_int(adapter); | ||
| 1537 | /* Ack ISR */ | ||
| 1538 | AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); | ||
| 1539 | if (status & ISR_RX_PKT) { | ||
| 1540 | if (likely(napi_schedule_prep(&adapter->napi))) { | ||
| 1541 | hw->intr_mask &= ~ISR_RX_PKT; | ||
| 1542 | AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); | ||
| 1543 | __napi_schedule(&adapter->napi); | ||
| 1544 | } | ||
| 1545 | } | ||
| 1546 | if (status & ISR_TX_PKT) | ||
| 1547 | atl1c_clean_tx_irq(adapter, atl1c_trans_normal); | ||
| 1548 | |||
| 1549 | handled = IRQ_HANDLED; | ||
| 1550 | /* check if PCIE PHY Link down */ | ||
| 1551 | if (status & ISR_ERROR) { | ||
| 1552 | if (netif_msg_hw(adapter)) | ||
| 1553 | dev_err(&pdev->dev, | ||
| 1554 | "atl1c hardware error (status = 0x%x)\n", | ||
| 1555 | status & ISR_ERROR); | ||
| 1556 | /* reset MAC */ | ||
| 1557 | hw->intr_mask &= ~ISR_ERROR; | ||
| 1558 | AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); | ||
| 1559 | schedule_work(&adapter->reset_task); | ||
| 1560 | break; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | if (status & ISR_OVER) | ||
| 1564 | if (netif_msg_intr(adapter)) | ||
| 1565 | dev_warn(&pdev->dev, | ||
| 1566 | "TX/RX over flow (status = 0x%x)\n", | ||
| 1567 | status & ISR_OVER); | ||
| 1568 | |||
| 1569 | /* link event */ | ||
| 1570 | if (status & (ISR_GPHY | ISR_MANUAL)) { | ||
| 1571 | adapter->net_stats.tx_carrier_errors++; | ||
| 1572 | atl1c_link_chg_event(adapter); | ||
| 1573 | break; | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | } while (--max_ints > 0); | ||
| 1577 | /* re-enable Interrupt*/ | ||
| 1578 | AT_WRITE_REG(&adapter->hw, REG_ISR, 0); | ||
| 1579 | return handled; | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, | ||
| 1583 | struct sk_buff *skb, struct atl1c_recv_ret_status *prrs) | ||
| 1584 | { | ||
| 1585 | /* | ||
| 1586 | * The pid field in RRS in not correct sometimes, so we | ||
| 1587 | * cannot figure out if the packet is fragmented or not, | ||
| 1588 | * so we tell the KERNEL CHECKSUM_NONE | ||
| 1589 | */ | ||
| 1590 | skb->ip_summed = CHECKSUM_NONE; | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid) | ||
| 1594 | { | ||
| 1595 | struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid]; | ||
| 1596 | struct pci_dev *pdev = adapter->pdev; | ||
| 1597 | struct atl1c_buffer *buffer_info, *next_info; | ||
| 1598 | struct sk_buff *skb; | ||
| 1599 | void *vir_addr = NULL; | ||
| 1600 | u16 num_alloc = 0; | ||
| 1601 | u16 rfd_next_to_use, next_next; | ||
| 1602 | struct atl1c_rx_free_desc *rfd_desc; | ||
| 1603 | |||
| 1604 | next_next = rfd_next_to_use = rfd_ring->next_to_use; | ||
| 1605 | if (++next_next == rfd_ring->count) | ||
| 1606 | next_next = 0; | ||
| 1607 | buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; | ||
| 1608 | next_info = &rfd_ring->buffer_info[next_next]; | ||
| 1609 | |||
| 1610 | while (next_info->state == ATL1_BUFFER_FREE) { | ||
| 1611 | rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); | ||
| 1612 | |||
| 1613 | skb = dev_alloc_skb(adapter->rx_buffer_len); | ||
| 1614 | if (unlikely(!skb)) { | ||
| 1615 | if (netif_msg_rx_err(adapter)) | ||
| 1616 | dev_warn(&pdev->dev, "alloc rx buffer failed\n"); | ||
| 1617 | break; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | /* | ||
| 1621 | * Make buffer alignment 2 beyond a 16 byte boundary | ||
| 1622 | * this will result in a 16 byte aligned IP header after | ||
| 1623 | * the 14 byte MAC header is removed | ||
| 1624 | */ | ||
| 1625 | vir_addr = skb->data; | ||
| 1626 | buffer_info->state = ATL1_BUFFER_BUSY; | ||
| 1627 | buffer_info->skb = skb; | ||
| 1628 | buffer_info->length = adapter->rx_buffer_len; | ||
| 1629 | buffer_info->dma = pci_map_single(pdev, vir_addr, | ||
| 1630 | buffer_info->length, | ||
| 1631 | PCI_DMA_FROMDEVICE); | ||
| 1632 | rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); | ||
| 1633 | rfd_next_to_use = next_next; | ||
| 1634 | if (++next_next == rfd_ring->count) | ||
| 1635 | next_next = 0; | ||
| 1636 | buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; | ||
| 1637 | next_info = &rfd_ring->buffer_info[next_next]; | ||
| 1638 | num_alloc++; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | if (num_alloc) { | ||
| 1642 | /* TODO: update mailbox here */ | ||
| 1643 | wmb(); | ||
| 1644 | rfd_ring->next_to_use = rfd_next_to_use; | ||
| 1645 | AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid], | ||
| 1646 | rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | return num_alloc; | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring, | ||
| 1653 | struct atl1c_recv_ret_status *rrs, u16 num) | ||
| 1654 | { | ||
| 1655 | u16 i; | ||
| 1656 | /* the relationship between rrd and rfd is one map one */ | ||
| 1657 | for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring, | ||
| 1658 | rrd_ring->next_to_clean)) { | ||
| 1659 | rrs->word3 &= ~RRS_RXD_UPDATED; | ||
| 1660 | if (++rrd_ring->next_to_clean == rrd_ring->count) | ||
| 1661 | rrd_ring->next_to_clean = 0; | ||
| 1662 | } | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, | ||
| 1666 | struct atl1c_recv_ret_status *rrs, u16 num) | ||
| 1667 | { | ||
| 1668 | u16 i; | ||
| 1669 | u16 rfd_index; | ||
| 1670 | struct atl1c_buffer *buffer_info = rfd_ring->buffer_info; | ||
| 1671 | |||
| 1672 | rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & | ||
| 1673 | RRS_RX_RFD_INDEX_MASK; | ||
| 1674 | for (i = 0; i < num; i++) { | ||
| 1675 | buffer_info[rfd_index].skb = NULL; | ||
| 1676 | buffer_info[rfd_index].state = ATL1_BUFFER_FREE; | ||
| 1677 | if (++rfd_index == rfd_ring->count) | ||
| 1678 | rfd_index = 0; | ||
| 1679 | } | ||
| 1680 | rfd_ring->next_to_clean = rfd_index; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, | ||
| 1684 | int *work_done, int work_to_do) | ||
| 1685 | { | ||
| 1686 | u16 rfd_num, rfd_index; | ||
| 1687 | u16 count = 0; | ||
| 1688 | u16 length; | ||
| 1689 | struct pci_dev *pdev = adapter->pdev; | ||
| 1690 | struct net_device *netdev = adapter->netdev; | ||
| 1691 | struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que]; | ||
| 1692 | struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que]; | ||
| 1693 | struct sk_buff *skb; | ||
| 1694 | struct atl1c_recv_ret_status *rrs; | ||
| 1695 | struct atl1c_buffer *buffer_info; | ||
| 1696 | |||
| 1697 | while (1) { | ||
| 1698 | if (*work_done >= work_to_do) | ||
| 1699 | break; | ||
| 1700 | rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean); | ||
| 1701 | if (likely(RRS_RXD_IS_VALID(rrs->word3))) { | ||
| 1702 | rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & | ||
| 1703 | RRS_RX_RFD_CNT_MASK; | ||
| 1704 | if (unlikely(rfd_num) != 1) | ||
| 1705 | /* TODO support mul rfd*/ | ||
| 1706 | if (netif_msg_rx_err(adapter)) | ||
| 1707 | dev_warn(&pdev->dev, | ||
| 1708 | "Multi rfd not support yet!\n"); | ||
| 1709 | goto rrs_checked; | ||
| 1710 | } else { | ||
| 1711 | break; | ||
| 1712 | } | ||
| 1713 | rrs_checked: | ||
| 1714 | atl1c_clean_rrd(rrd_ring, rrs, rfd_num); | ||
| 1715 | if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) { | ||
| 1716 | atl1c_clean_rfd(rfd_ring, rrs, rfd_num); | ||
| 1717 | if (netif_msg_rx_err(adapter)) | ||
| 1718 | dev_warn(&pdev->dev, | ||
| 1719 | "wrong packet! rrs word3 is %x\n", | ||
| 1720 | rrs->word3); | ||
| 1721 | continue; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) & | ||
| 1725 | RRS_PKT_SIZE_MASK); | ||
| 1726 | /* Good Receive */ | ||
| 1727 | if (likely(rfd_num == 1)) { | ||
| 1728 | rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & | ||
| 1729 | RRS_RX_RFD_INDEX_MASK; | ||
| 1730 | buffer_info = &rfd_ring->buffer_info[rfd_index]; | ||
| 1731 | pci_unmap_single(pdev, buffer_info->dma, | ||
| 1732 | buffer_info->length, PCI_DMA_FROMDEVICE); | ||
| 1733 | skb = buffer_info->skb; | ||
| 1734 | } else { | ||
| 1735 | /* TODO */ | ||
| 1736 | if (netif_msg_rx_err(adapter)) | ||
| 1737 | dev_warn(&pdev->dev, | ||
| 1738 | "Multi rfd not support yet!\n"); | ||
| 1739 | break; | ||
| 1740 | } | ||
| 1741 | atl1c_clean_rfd(rfd_ring, rrs, rfd_num); | ||
| 1742 | skb_put(skb, length - ETH_FCS_LEN); | ||
| 1743 | skb->protocol = eth_type_trans(skb, netdev); | ||
| 1744 | skb->dev = netdev; | ||
| 1745 | atl1c_rx_checksum(adapter, skb, rrs); | ||
| 1746 | if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) { | ||
| 1747 | u16 vlan; | ||
| 1748 | |||
| 1749 | AT_TAG_TO_VLAN(rrs->vlan_tag, vlan); | ||
| 1750 | vlan = le16_to_cpu(vlan); | ||
| 1751 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan); | ||
| 1752 | } else | ||
| 1753 | netif_receive_skb(skb); | ||
| 1754 | |||
| 1755 | netdev->last_rx = jiffies; | ||
| 1756 | (*work_done)++; | ||
| 1757 | count++; | ||
| 1758 | } | ||
| 1759 | if (count) | ||
| 1760 | atl1c_alloc_rx_buffer(adapter, que); | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | /* | ||
| 1764 | * atl1c_clean - NAPI Rx polling callback | ||
| 1765 | * @adapter: board private structure | ||
| 1766 | */ | ||
| 1767 | static int atl1c_clean(struct napi_struct *napi, int budget) | ||
| 1768 | { | ||
| 1769 | struct atl1c_adapter *adapter = | ||
| 1770 | container_of(napi, struct atl1c_adapter, napi); | ||
| 1771 | int work_done = 0; | ||
| 1772 | |||
| 1773 | /* Keep link state information with original netdev */ | ||
| 1774 | if (!netif_carrier_ok(adapter->netdev)) | ||
| 1775 | goto quit_polling; | ||
| 1776 | /* just enable one RXQ */ | ||
| 1777 | atl1c_clean_rx_irq(adapter, 0, &work_done, budget); | ||
| 1778 | |||
| 1779 | if (work_done < budget) { | ||
| 1780 | quit_polling: | ||
| 1781 | napi_complete(napi); | ||
| 1782 | adapter->hw.intr_mask |= ISR_RX_PKT; | ||
| 1783 | AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); | ||
| 1784 | } | ||
| 1785 | return work_done; | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1789 | |||
| 1790 | /* | ||
| 1791 | * Polling 'interrupt' - used by things like netconsole to send skbs | ||
| 1792 | * without having to re-enable interrupts. It's not called while | ||
| 1793 | * the interrupt routine is executing. | ||
| 1794 | */ | ||
| 1795 | static void atl1c_netpoll(struct net_device *netdev) | ||
| 1796 | { | ||
| 1797 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 1798 | |||
| 1799 | disable_irq(adapter->pdev->irq); | ||
| 1800 | atl1c_intr(adapter->pdev->irq, netdev); | ||
| 1801 | enable_irq(adapter->pdev->irq); | ||
| 1802 | } | ||
| 1803 | #endif | ||
| 1804 | |||
| 1805 | static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type) | ||
| 1806 | { | ||
| 1807 | struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; | ||
| 1808 | u16 next_to_use = 0; | ||
| 1809 | u16 next_to_clean = 0; | ||
| 1810 | |||
| 1811 | next_to_clean = atomic_read(&tpd_ring->next_to_clean); | ||
| 1812 | next_to_use = tpd_ring->next_to_use; | ||
| 1813 | |||
| 1814 | return (u16)(next_to_clean > next_to_use) ? | ||
| 1815 | (next_to_clean - next_to_use - 1) : | ||
| 1816 | (tpd_ring->count + next_to_clean - next_to_use - 1); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | /* | ||
| 1820 | * get next usable tpd | ||
| 1821 | * Note: should call atl1c_tdp_avail to make sure | ||
| 1822 | * there is enough tpd to use | ||
| 1823 | */ | ||
| 1824 | static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter, | ||
| 1825 | enum atl1c_trans_queue type) | ||
| 1826 | { | ||
| 1827 | struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; | ||
| 1828 | struct atl1c_tpd_desc *tpd_desc; | ||
| 1829 | u16 next_to_use = 0; | ||
| 1830 | |||
| 1831 | next_to_use = tpd_ring->next_to_use; | ||
| 1832 | if (++tpd_ring->next_to_use == tpd_ring->count) | ||
| 1833 | tpd_ring->next_to_use = 0; | ||
| 1834 | tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use); | ||
| 1835 | memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc)); | ||
| 1836 | return tpd_desc; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | static struct atl1c_buffer * | ||
| 1840 | atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd) | ||
| 1841 | { | ||
| 1842 | struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; | ||
| 1843 | |||
| 1844 | return &tpd_ring->buffer_info[tpd - | ||
| 1845 | (struct atl1c_tpd_desc *)tpd_ring->desc]; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | /* Calculate the transmit packet descript needed*/ | ||
| 1849 | static u16 atl1c_cal_tpd_req(const struct sk_buff *skb) | ||
| 1850 | { | ||
| 1851 | u16 tpd_req; | ||
| 1852 | u16 proto_hdr_len = 0; | ||
| 1853 | |||
| 1854 | tpd_req = skb_shinfo(skb)->nr_frags + 1; | ||
| 1855 | |||
| 1856 | if (skb_is_gso(skb)) { | ||
| 1857 | proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); | ||
| 1858 | if (proto_hdr_len < skb_headlen(skb)) | ||
| 1859 | tpd_req++; | ||
| 1860 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) | ||
| 1861 | tpd_req++; | ||
| 1862 | } | ||
| 1863 | return tpd_req; | ||
| 1864 | } | ||
| 1865 | |||
| 1866 | static int atl1c_tso_csum(struct atl1c_adapter *adapter, | ||
| 1867 | struct sk_buff *skb, | ||
| 1868 | struct atl1c_tpd_desc **tpd, | ||
| 1869 | enum atl1c_trans_queue type) | ||
| 1870 | { | ||
| 1871 | struct pci_dev *pdev = adapter->pdev; | ||
| 1872 | u8 hdr_len; | ||
| 1873 | u32 real_len; | ||
| 1874 | unsigned short offload_type; | ||
| 1875 | int err; | ||
| 1876 | |||
| 1877 | if (skb_is_gso(skb)) { | ||
| 1878 | if (skb_header_cloned(skb)) { | ||
| 1879 | err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | ||
| 1880 | if (unlikely(err)) | ||
| 1881 | return -1; | ||
| 1882 | } | ||
| 1883 | offload_type = skb_shinfo(skb)->gso_type; | ||
| 1884 | |||
| 1885 | if (offload_type & SKB_GSO_TCPV4) { | ||
| 1886 | real_len = (((unsigned char *)ip_hdr(skb) - skb->data) | ||
| 1887 | + ntohs(ip_hdr(skb)->tot_len)); | ||
| 1888 | |||
| 1889 | if (real_len < skb->len) | ||
| 1890 | pskb_trim(skb, real_len); | ||
| 1891 | |||
| 1892 | hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); | ||
| 1893 | if (unlikely(skb->len == hdr_len)) { | ||
| 1894 | /* only xsum need */ | ||
| 1895 | if (netif_msg_tx_queued(adapter)) | ||
| 1896 | dev_warn(&pdev->dev, | ||
| 1897 | "IPV4 tso with zero data??\n"); | ||
| 1898 | goto check_sum; | ||
| 1899 | } else { | ||
| 1900 | ip_hdr(skb)->check = 0; | ||
| 1901 | tcp_hdr(skb)->check = ~csum_tcpudp_magic( | ||
| 1902 | ip_hdr(skb)->saddr, | ||
| 1903 | ip_hdr(skb)->daddr, | ||
| 1904 | 0, IPPROTO_TCP, 0); | ||
| 1905 | (*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT; | ||
| 1906 | } | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | if (offload_type & SKB_GSO_TCPV6) { | ||
| 1910 | struct atl1c_tpd_ext_desc *etpd = | ||
| 1911 | *(struct atl1c_tpd_ext_desc **)(tpd); | ||
| 1912 | |||
| 1913 | memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc)); | ||
| 1914 | *tpd = atl1c_get_tpd(adapter, type); | ||
| 1915 | ipv6_hdr(skb)->payload_len = 0; | ||
| 1916 | /* check payload == 0 byte ? */ | ||
| 1917 | hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); | ||
| 1918 | if (unlikely(skb->len == hdr_len)) { | ||
| 1919 | /* only xsum need */ | ||
| 1920 | if (netif_msg_tx_queued(adapter)) | ||
| 1921 | dev_warn(&pdev->dev, | ||
| 1922 | "IPV6 tso with zero data??\n"); | ||
| 1923 | goto check_sum; | ||
| 1924 | } else | ||
| 1925 | tcp_hdr(skb)->check = ~csum_ipv6_magic( | ||
| 1926 | &ipv6_hdr(skb)->saddr, | ||
| 1927 | &ipv6_hdr(skb)->daddr, | ||
| 1928 | 0, IPPROTO_TCP, 0); | ||
| 1929 | etpd->word1 |= 1 << TPD_LSO_EN_SHIFT; | ||
| 1930 | etpd->word1 |= 1 << TPD_LSO_VER_SHIFT; | ||
| 1931 | etpd->pkt_len = cpu_to_le32(skb->len); | ||
| 1932 | (*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT; | ||
| 1933 | } | ||
| 1934 | |||
| 1935 | (*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT; | ||
| 1936 | (*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) << | ||
| 1937 | TPD_TCPHDR_OFFSET_SHIFT; | ||
| 1938 | (*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) << | ||
| 1939 | TPD_MSS_SHIFT; | ||
| 1940 | return 0; | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | check_sum: | ||
| 1944 | if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { | ||
| 1945 | u8 css, cso; | ||
| 1946 | cso = skb_transport_offset(skb); | ||
| 1947 | |||
| 1948 | if (unlikely(cso & 0x1)) { | ||
| 1949 | if (netif_msg_tx_err(adapter)) | ||
| 1950 | dev_err(&adapter->pdev->dev, | ||
| 1951 | "payload offset should not an event number\n"); | ||
| 1952 | return -1; | ||
| 1953 | } else { | ||
| 1954 | css = cso + skb->csum_offset; | ||
| 1955 | |||
| 1956 | (*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) << | ||
| 1957 | TPD_PLOADOFFSET_SHIFT; | ||
| 1958 | (*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) << | ||
| 1959 | TPD_CCSUM_OFFSET_SHIFT; | ||
| 1960 | (*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT; | ||
| 1961 | } | ||
| 1962 | } | ||
| 1963 | return 0; | ||
| 1964 | } | ||
| 1965 | |||
| 1966 | static void atl1c_tx_map(struct atl1c_adapter *adapter, | ||
| 1967 | struct sk_buff *skb, struct atl1c_tpd_desc *tpd, | ||
| 1968 | enum atl1c_trans_queue type) | ||
| 1969 | { | ||
| 1970 | struct atl1c_tpd_desc *use_tpd = NULL; | ||
| 1971 | struct atl1c_buffer *buffer_info = NULL; | ||
| 1972 | u16 buf_len = skb_headlen(skb); | ||
| 1973 | u16 map_len = 0; | ||
| 1974 | u16 mapped_len = 0; | ||
| 1975 | u16 hdr_len = 0; | ||
| 1976 | u16 nr_frags; | ||
| 1977 | u16 f; | ||
| 1978 | int tso; | ||
| 1979 | |||
| 1980 | nr_frags = skb_shinfo(skb)->nr_frags; | ||
| 1981 | tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK; | ||
| 1982 | if (tso) { | ||
| 1983 | /* TSO */ | ||
| 1984 | map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); | ||
| 1985 | use_tpd = tpd; | ||
| 1986 | |||
| 1987 | buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); | ||
| 1988 | buffer_info->length = map_len; | ||
| 1989 | buffer_info->dma = pci_map_single(adapter->pdev, | ||
| 1990 | skb->data, hdr_len, PCI_DMA_TODEVICE); | ||
| 1991 | buffer_info->state = ATL1_BUFFER_BUSY; | ||
| 1992 | mapped_len += map_len; | ||
| 1993 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | ||
| 1994 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | if (mapped_len < buf_len) { | ||
| 1998 | /* mapped_len == 0, means we should use the first tpd, | ||
| 1999 | which is given by caller */ | ||
| 2000 | if (mapped_len == 0) | ||
| 2001 | use_tpd = tpd; | ||
| 2002 | else { | ||
| 2003 | use_tpd = atl1c_get_tpd(adapter, type); | ||
| 2004 | memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); | ||
| 2005 | use_tpd = atl1c_get_tpd(adapter, type); | ||
| 2006 | memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); | ||
| 2007 | } | ||
| 2008 | buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); | ||
| 2009 | buffer_info->length = buf_len - mapped_len; | ||
| 2010 | buffer_info->dma = | ||
| 2011 | pci_map_single(adapter->pdev, skb->data + mapped_len, | ||
| 2012 | buffer_info->length, PCI_DMA_TODEVICE); | ||
| 2013 | buffer_info->state = ATL1_BUFFER_BUSY; | ||
| 2014 | |||
| 2015 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | ||
| 2016 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | ||
| 2017 | } | ||
| 2018 | |||
| 2019 | for (f = 0; f < nr_frags; f++) { | ||
| 2020 | struct skb_frag_struct *frag; | ||
| 2021 | |||
| 2022 | frag = &skb_shinfo(skb)->frags[f]; | ||
| 2023 | |||
| 2024 | use_tpd = atl1c_get_tpd(adapter, type); | ||
| 2025 | memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); | ||
| 2026 | |||
| 2027 | buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); | ||
| 2028 | buffer_info->length = frag->size; | ||
| 2029 | buffer_info->dma = | ||
| 2030 | pci_map_page(adapter->pdev, frag->page, | ||
| 2031 | frag->page_offset, | ||
| 2032 | buffer_info->length, | ||
| 2033 | PCI_DMA_TODEVICE); | ||
| 2034 | buffer_info->state = ATL1_BUFFER_BUSY; | ||
| 2035 | |||
| 2036 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | ||
| 2037 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | /* The last tpd */ | ||
| 2041 | use_tpd->word1 |= 1 << TPD_EOP_SHIFT; | ||
| 2042 | /* The last buffer info contain the skb address, | ||
| 2043 | so it will be free after unmap */ | ||
| 2044 | buffer_info->skb = skb; | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, | ||
| 2048 | struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) | ||
| 2049 | { | ||
| 2050 | struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; | ||
| 2051 | u32 prod_data; | ||
| 2052 | |||
| 2053 | AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data); | ||
| 2054 | switch (type) { | ||
| 2055 | case atl1c_trans_high: | ||
| 2056 | prod_data &= 0xFFFF0000; | ||
| 2057 | prod_data |= tpd_ring->next_to_use & 0xFFFF; | ||
| 2058 | break; | ||
| 2059 | case atl1c_trans_normal: | ||
| 2060 | prod_data &= 0x0000FFFF; | ||
| 2061 | prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16; | ||
| 2062 | break; | ||
| 2063 | default: | ||
| 2064 | break; | ||
| 2065 | } | ||
| 2066 | wmb(); | ||
| 2067 | AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data); | ||
| 2068 | } | ||
| 2069 | |||
| 2070 | static int atl1c_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | ||
| 2071 | { | ||
| 2072 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2073 | unsigned long flags; | ||
| 2074 | u16 tpd_req = 1; | ||
| 2075 | struct atl1c_tpd_desc *tpd; | ||
| 2076 | enum atl1c_trans_queue type = atl1c_trans_normal; | ||
| 2077 | |||
| 2078 | if (test_bit(__AT_DOWN, &adapter->flags)) { | ||
| 2079 | dev_kfree_skb_any(skb); | ||
| 2080 | return NETDEV_TX_OK; | ||
| 2081 | } | ||
| 2082 | |||
| 2083 | tpd_req = atl1c_cal_tpd_req(skb); | ||
| 2084 | if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) { | ||
| 2085 | if (netif_msg_pktdata(adapter)) | ||
| 2086 | dev_info(&adapter->pdev->dev, "tx locked\n"); | ||
| 2087 | return NETDEV_TX_LOCKED; | ||
| 2088 | } | ||
| 2089 | if (skb->mark == 0x01) | ||
| 2090 | type = atl1c_trans_high; | ||
| 2091 | else | ||
| 2092 | type = atl1c_trans_normal; | ||
| 2093 | |||
| 2094 | if (atl1c_tpd_avail(adapter, type) < tpd_req) { | ||
| 2095 | /* no enough descriptor, just stop queue */ | ||
| 2096 | netif_stop_queue(netdev); | ||
| 2097 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
| 2098 | return NETDEV_TX_BUSY; | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | tpd = atl1c_get_tpd(adapter, type); | ||
| 2102 | |||
| 2103 | /* do TSO and check sum */ | ||
| 2104 | if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) { | ||
| 2105 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
| 2106 | dev_kfree_skb_any(skb); | ||
| 2107 | return NETDEV_TX_OK; | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { | ||
| 2111 | u16 vlan = vlan_tx_tag_get(skb); | ||
| 2112 | __le16 tag; | ||
| 2113 | |||
| 2114 | vlan = cpu_to_le16(vlan); | ||
| 2115 | AT_VLAN_TO_TAG(vlan, tag); | ||
| 2116 | tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT; | ||
| 2117 | tpd->vlan_tag = tag; | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | if (skb_network_offset(skb) != ETH_HLEN) | ||
| 2121 | tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ | ||
| 2122 | |||
| 2123 | atl1c_tx_map(adapter, skb, tpd, type); | ||
| 2124 | atl1c_tx_queue(adapter, skb, tpd, type); | ||
| 2125 | |||
| 2126 | netdev->trans_start = jiffies; | ||
| 2127 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
| 2128 | return NETDEV_TX_OK; | ||
| 2129 | } | ||
| 2130 | |||
| 2131 | static void atl1c_free_irq(struct atl1c_adapter *adapter) | ||
| 2132 | { | ||
| 2133 | struct net_device *netdev = adapter->netdev; | ||
| 2134 | |||
| 2135 | free_irq(adapter->pdev->irq, netdev); | ||
| 2136 | |||
| 2137 | if (adapter->have_msi) | ||
| 2138 | pci_disable_msi(adapter->pdev); | ||
| 2139 | } | ||
| 2140 | |||
| 2141 | static int atl1c_request_irq(struct atl1c_adapter *adapter) | ||
| 2142 | { | ||
| 2143 | struct pci_dev *pdev = adapter->pdev; | ||
| 2144 | struct net_device *netdev = adapter->netdev; | ||
| 2145 | int flags = 0; | ||
| 2146 | int err = 0; | ||
| 2147 | |||
| 2148 | adapter->have_msi = true; | ||
| 2149 | err = pci_enable_msi(adapter->pdev); | ||
| 2150 | if (err) { | ||
| 2151 | if (netif_msg_ifup(adapter)) | ||
| 2152 | dev_err(&pdev->dev, | ||
| 2153 | "Unable to allocate MSI interrupt Error: %d\n", | ||
| 2154 | err); | ||
| 2155 | adapter->have_msi = false; | ||
| 2156 | } else | ||
| 2157 | netdev->irq = pdev->irq; | ||
| 2158 | |||
| 2159 | if (!adapter->have_msi) | ||
| 2160 | flags |= IRQF_SHARED; | ||
| 2161 | err = request_irq(adapter->pdev->irq, &atl1c_intr, flags, | ||
| 2162 | netdev->name, netdev); | ||
| 2163 | if (err) { | ||
| 2164 | if (netif_msg_ifup(adapter)) | ||
| 2165 | dev_err(&pdev->dev, | ||
| 2166 | "Unable to allocate interrupt Error: %d\n", | ||
| 2167 | err); | ||
| 2168 | if (adapter->have_msi) | ||
| 2169 | pci_disable_msi(adapter->pdev); | ||
| 2170 | return err; | ||
| 2171 | } | ||
| 2172 | if (netif_msg_ifup(adapter)) | ||
| 2173 | dev_dbg(&pdev->dev, "atl1c_request_irq OK\n"); | ||
| 2174 | return err; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | int atl1c_up(struct atl1c_adapter *adapter) | ||
| 2178 | { | ||
| 2179 | struct net_device *netdev = adapter->netdev; | ||
| 2180 | int num; | ||
| 2181 | int err; | ||
| 2182 | int i; | ||
| 2183 | |||
| 2184 | netif_carrier_off(netdev); | ||
| 2185 | atl1c_init_ring_ptrs(adapter); | ||
| 2186 | atl1c_set_multi(netdev); | ||
| 2187 | atl1c_restore_vlan(adapter); | ||
| 2188 | |||
| 2189 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
| 2190 | num = atl1c_alloc_rx_buffer(adapter, i); | ||
| 2191 | if (unlikely(num == 0)) { | ||
| 2192 | err = -ENOMEM; | ||
| 2193 | goto err_alloc_rx; | ||
| 2194 | } | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | if (atl1c_configure(adapter)) { | ||
| 2198 | err = -EIO; | ||
| 2199 | goto err_up; | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | err = atl1c_request_irq(adapter); | ||
| 2203 | if (unlikely(err)) | ||
| 2204 | goto err_up; | ||
| 2205 | |||
| 2206 | clear_bit(__AT_DOWN, &adapter->flags); | ||
| 2207 | napi_enable(&adapter->napi); | ||
| 2208 | atl1c_irq_enable(adapter); | ||
| 2209 | atl1c_check_link_status(adapter); | ||
| 2210 | netif_start_queue(netdev); | ||
| 2211 | return err; | ||
| 2212 | |||
| 2213 | err_up: | ||
| 2214 | err_alloc_rx: | ||
| 2215 | atl1c_clean_rx_ring(adapter); | ||
| 2216 | return err; | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | void atl1c_down(struct atl1c_adapter *adapter) | ||
| 2220 | { | ||
| 2221 | struct net_device *netdev = adapter->netdev; | ||
| 2222 | |||
| 2223 | atl1c_del_timer(adapter); | ||
| 2224 | atl1c_cancel_work(adapter); | ||
| 2225 | |||
| 2226 | /* signal that we're down so the interrupt handler does not | ||
| 2227 | * reschedule our watchdog timer */ | ||
| 2228 | set_bit(__AT_DOWN, &adapter->flags); | ||
| 2229 | netif_carrier_off(netdev); | ||
| 2230 | napi_disable(&adapter->napi); | ||
| 2231 | atl1c_irq_disable(adapter); | ||
| 2232 | atl1c_free_irq(adapter); | ||
| 2233 | AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT); | ||
| 2234 | /* reset MAC to disable all RX/TX */ | ||
| 2235 | atl1c_reset_mac(&adapter->hw); | ||
| 2236 | msleep(1); | ||
| 2237 | |||
| 2238 | adapter->link_speed = SPEED_0; | ||
| 2239 | adapter->link_duplex = -1; | ||
| 2240 | atl1c_clean_tx_ring(adapter, atl1c_trans_normal); | ||
| 2241 | atl1c_clean_tx_ring(adapter, atl1c_trans_high); | ||
| 2242 | atl1c_clean_rx_ring(adapter); | ||
| 2243 | } | ||
| 2244 | |||
| 2245 | /* | ||
| 2246 | * atl1c_open - Called when a network interface is made active | ||
| 2247 | * @netdev: network interface device structure | ||
| 2248 | * | ||
| 2249 | * Returns 0 on success, negative value on failure | ||
| 2250 | * | ||
| 2251 | * The open entry point is called when a network interface is made | ||
| 2252 | * active by the system (IFF_UP). At this point all resources needed | ||
| 2253 | * for transmit and receive operations are allocated, the interrupt | ||
| 2254 | * handler is registered with the OS, the watchdog timer is started, | ||
| 2255 | * and the stack is notified that the interface is ready. | ||
| 2256 | */ | ||
| 2257 | static int atl1c_open(struct net_device *netdev) | ||
| 2258 | { | ||
| 2259 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2260 | int err; | ||
| 2261 | |||
| 2262 | /* disallow open during test */ | ||
| 2263 | if (test_bit(__AT_TESTING, &adapter->flags)) | ||
| 2264 | return -EBUSY; | ||
| 2265 | |||
| 2266 | /* allocate rx/tx dma buffer & descriptors */ | ||
| 2267 | err = atl1c_setup_ring_resources(adapter); | ||
| 2268 | if (unlikely(err)) | ||
| 2269 | return err; | ||
| 2270 | |||
| 2271 | err = atl1c_up(adapter); | ||
| 2272 | if (unlikely(err)) | ||
| 2273 | goto err_up; | ||
| 2274 | |||
| 2275 | if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { | ||
| 2276 | u32 phy_data; | ||
| 2277 | |||
| 2278 | AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data); | ||
| 2279 | phy_data |= MDIO_AP_EN; | ||
| 2280 | AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data); | ||
| 2281 | } | ||
| 2282 | return 0; | ||
| 2283 | |||
| 2284 | err_up: | ||
| 2285 | atl1c_free_irq(adapter); | ||
| 2286 | atl1c_free_ring_resources(adapter); | ||
| 2287 | atl1c_reset_mac(&adapter->hw); | ||
| 2288 | return err; | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | /* | ||
| 2292 | * atl1c_close - Disables a network interface | ||
| 2293 | * @netdev: network interface device structure | ||
| 2294 | * | ||
| 2295 | * Returns 0, this is not allowed to fail | ||
| 2296 | * | ||
| 2297 | * The close entry point is called when an interface is de-activated | ||
| 2298 | * by the OS. The hardware is still under the drivers control, but | ||
| 2299 | * needs to be disabled. A global MAC reset is issued to stop the | ||
| 2300 | * hardware, and all transmit and receive resources are freed. | ||
| 2301 | */ | ||
| 2302 | static int atl1c_close(struct net_device *netdev) | ||
| 2303 | { | ||
| 2304 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2305 | |||
| 2306 | WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); | ||
| 2307 | atl1c_down(adapter); | ||
| 2308 | atl1c_free_ring_resources(adapter); | ||
| 2309 | return 0; | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 2313 | { | ||
| 2314 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2315 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2316 | struct atl1c_hw *hw = &adapter->hw; | ||
| 2317 | u32 ctrl; | ||
| 2318 | u32 mac_ctrl_data; | ||
| 2319 | u32 master_ctrl_data; | ||
| 2320 | u32 wol_ctrl_data; | ||
| 2321 | u16 mii_bmsr_data; | ||
| 2322 | u16 save_autoneg_advertised; | ||
| 2323 | u16 mii_intr_status_data; | ||
| 2324 | u32 wufc = adapter->wol; | ||
| 2325 | u32 i; | ||
| 2326 | int retval = 0; | ||
| 2327 | |||
| 2328 | if (netif_running(netdev)) { | ||
| 2329 | WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); | ||
| 2330 | atl1c_down(adapter); | ||
| 2331 | } | ||
| 2332 | netif_device_detach(netdev); | ||
| 2333 | atl1c_disable_l0s_l1(hw); | ||
| 2334 | retval = pci_save_state(pdev); | ||
| 2335 | if (retval) | ||
| 2336 | return retval; | ||
| 2337 | if (wufc) { | ||
| 2338 | AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); | ||
| 2339 | master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; | ||
| 2340 | |||
| 2341 | /* get link status */ | ||
| 2342 | atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data); | ||
| 2343 | atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data); | ||
| 2344 | save_autoneg_advertised = hw->autoneg_advertised; | ||
| 2345 | hw->autoneg_advertised = ADVERTISED_10baseT_Half; | ||
| 2346 | if (atl1c_restart_autoneg(hw) != 0) | ||
| 2347 | if (netif_msg_link(adapter)) | ||
| 2348 | dev_warn(&pdev->dev, "phy autoneg failed\n"); | ||
| 2349 | hw->phy_configured = false; /* re-init PHY when resume */ | ||
| 2350 | hw->autoneg_advertised = save_autoneg_advertised; | ||
| 2351 | /* turn on magic packet wol */ | ||
| 2352 | if (wufc & AT_WUFC_MAG) | ||
| 2353 | wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; | ||
| 2354 | |||
| 2355 | if (wufc & AT_WUFC_LNKC) { | ||
| 2356 | for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { | ||
| 2357 | msleep(100); | ||
| 2358 | atl1c_read_phy_reg(hw, MII_BMSR, | ||
| 2359 | (u16 *)&mii_bmsr_data); | ||
| 2360 | if (mii_bmsr_data & BMSR_LSTATUS) | ||
| 2361 | break; | ||
| 2362 | } | ||
| 2363 | if ((mii_bmsr_data & BMSR_LSTATUS) == 0) | ||
| 2364 | if (netif_msg_link(adapter)) | ||
| 2365 | dev_warn(&pdev->dev, | ||
| 2366 | "%s: Link may change" | ||
| 2367 | "when suspend\n", | ||
| 2368 | atl1c_driver_name); | ||
| 2369 | wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; | ||
| 2370 | /* only link up can wake up */ | ||
| 2371 | if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { | ||
| 2372 | if (netif_msg_link(adapter)) | ||
| 2373 | dev_err(&pdev->dev, | ||
| 2374 | "%s: read write phy " | ||
| 2375 | "register failed.\n", | ||
| 2376 | atl1c_driver_name); | ||
| 2377 | goto wol_dis; | ||
| 2378 | } | ||
| 2379 | } | ||
| 2380 | /* clear phy interrupt */ | ||
| 2381 | atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); | ||
| 2382 | /* Config MAC Ctrl register */ | ||
| 2383 | mac_ctrl_data = MAC_CTRL_RX_EN; | ||
| 2384 | /* set to 10/100M halt duplex */ | ||
| 2385 | mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; | ||
| 2386 | mac_ctrl_data |= (((u32)adapter->hw.preamble_len & | ||
| 2387 | MAC_CTRL_PRMLEN_MASK) << | ||
| 2388 | MAC_CTRL_PRMLEN_SHIFT); | ||
| 2389 | |||
| 2390 | if (adapter->vlgrp) | ||
| 2391 | mac_ctrl_data |= MAC_CTRL_RMV_VLAN; | ||
| 2392 | |||
| 2393 | /* magic packet maybe Broadcast&multicast&Unicast frame */ | ||
| 2394 | if (wufc & AT_WUFC_MAG) | ||
| 2395 | mac_ctrl_data |= MAC_CTRL_BC_EN; | ||
| 2396 | |||
| 2397 | if (netif_msg_hw(adapter)) | ||
| 2398 | dev_dbg(&pdev->dev, | ||
| 2399 | "%s: suspend MAC=0x%x\n", | ||
| 2400 | atl1c_driver_name, mac_ctrl_data); | ||
| 2401 | AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); | ||
| 2402 | AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); | ||
| 2403 | AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); | ||
| 2404 | |||
| 2405 | /* pcie patch */ | ||
| 2406 | AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl); | ||
| 2407 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; | ||
| 2408 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); | ||
| 2409 | |||
| 2410 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | ||
| 2411 | goto suspend_exit; | ||
| 2412 | } | ||
| 2413 | wol_dis: | ||
| 2414 | |||
| 2415 | /* WOL disabled */ | ||
| 2416 | AT_WRITE_REG(hw, REG_WOL_CTRL, 0); | ||
| 2417 | |||
| 2418 | /* pcie patch */ | ||
| 2419 | AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl); | ||
| 2420 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; | ||
| 2421 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); | ||
| 2422 | |||
| 2423 | atl1c_phy_disable(hw); | ||
| 2424 | hw->phy_configured = false; /* re-init PHY when resume */ | ||
| 2425 | |||
| 2426 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
| 2427 | suspend_exit: | ||
| 2428 | |||
| 2429 | pci_disable_device(pdev); | ||
| 2430 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 2431 | |||
| 2432 | return 0; | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | static int atl1c_resume(struct pci_dev *pdev) | ||
| 2436 | { | ||
| 2437 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2438 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2439 | |||
| 2440 | pci_set_power_state(pdev, PCI_D0); | ||
| 2441 | pci_restore_state(pdev); | ||
| 2442 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
| 2443 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
| 2444 | |||
| 2445 | AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); | ||
| 2446 | |||
| 2447 | atl1c_phy_reset(&adapter->hw); | ||
| 2448 | atl1c_reset_mac(&adapter->hw); | ||
| 2449 | netif_device_attach(netdev); | ||
| 2450 | if (netif_running(netdev)) | ||
| 2451 | atl1c_up(adapter); | ||
| 2452 | |||
| 2453 | return 0; | ||
| 2454 | } | ||
| 2455 | |||
| 2456 | static void atl1c_shutdown(struct pci_dev *pdev) | ||
| 2457 | { | ||
| 2458 | atl1c_suspend(pdev, PMSG_SUSPEND); | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | static const struct net_device_ops atl1c_netdev_ops = { | ||
| 2462 | .ndo_open = atl1c_open, | ||
| 2463 | .ndo_stop = atl1c_close, | ||
| 2464 | .ndo_validate_addr = eth_validate_addr, | ||
| 2465 | .ndo_start_xmit = atl1c_xmit_frame, | ||
| 2466 | .ndo_set_mac_address = atl1c_set_mac_addr, | ||
| 2467 | .ndo_set_multicast_list = atl1c_set_multi, | ||
| 2468 | .ndo_change_mtu = atl1c_change_mtu, | ||
| 2469 | .ndo_do_ioctl = atl1c_ioctl, | ||
| 2470 | .ndo_tx_timeout = atl1c_tx_timeout, | ||
| 2471 | .ndo_get_stats = atl1c_get_stats, | ||
| 2472 | .ndo_vlan_rx_register = atl1c_vlan_rx_register, | ||
| 2473 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 2474 | .ndo_poll_controller = atl1c_netpoll, | ||
| 2475 | #endif | ||
| 2476 | }; | ||
| 2477 | |||
| 2478 | static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) | ||
| 2479 | { | ||
| 2480 | SET_NETDEV_DEV(netdev, &pdev->dev); | ||
| 2481 | pci_set_drvdata(pdev, netdev); | ||
| 2482 | |||
| 2483 | netdev->irq = pdev->irq; | ||
| 2484 | netdev->netdev_ops = &atl1c_netdev_ops; | ||
| 2485 | netdev->watchdog_timeo = AT_TX_WATCHDOG; | ||
| 2486 | atl1c_set_ethtool_ops(netdev); | ||
| 2487 | |||
| 2488 | /* TODO: add when ready */ | ||
| 2489 | netdev->features = NETIF_F_SG | | ||
| 2490 | NETIF_F_HW_CSUM | | ||
| 2491 | NETIF_F_HW_VLAN_TX | | ||
| 2492 | NETIF_F_HW_VLAN_RX | | ||
| 2493 | NETIF_F_TSO | | ||
| 2494 | NETIF_F_TSO6; | ||
| 2495 | return 0; | ||
| 2496 | } | ||
| 2497 | |||
| 2498 | /* | ||
| 2499 | * atl1c_probe - Device Initialization Routine | ||
| 2500 | * @pdev: PCI device information struct | ||
| 2501 | * @ent: entry in atl1c_pci_tbl | ||
| 2502 | * | ||
| 2503 | * Returns 0 on success, negative on failure | ||
| 2504 | * | ||
| 2505 | * atl1c_probe initializes an adapter identified by a pci_dev structure. | ||
| 2506 | * The OS initialization, configuring of the adapter private structure, | ||
| 2507 | * and a hardware reset occur. | ||
| 2508 | */ | ||
| 2509 | static int __devinit atl1c_probe(struct pci_dev *pdev, | ||
| 2510 | const struct pci_device_id *ent) | ||
| 2511 | { | ||
| 2512 | struct net_device *netdev; | ||
| 2513 | struct atl1c_adapter *adapter; | ||
| 2514 | static int cards_found; | ||
| 2515 | |||
| 2516 | int err = 0; | ||
| 2517 | |||
| 2518 | /* enable device (incl. PCI PM wakeup and hotplug setup) */ | ||
| 2519 | err = pci_enable_device_mem(pdev); | ||
| 2520 | if (err) { | ||
| 2521 | dev_err(&pdev->dev, "cannot enable PCI device\n"); | ||
| 2522 | return err; | ||
| 2523 | } | ||
| 2524 | |||
| 2525 | /* | ||
| 2526 | * The atl1c chip can DMA to 64-bit addresses, but it uses a single | ||
| 2527 | * shared register for the high 32 bits, so only a single, aligned, | ||
| 2528 | * 4 GB physical address range can be used at a time. | ||
| 2529 | * | ||
| 2530 | * Supporting 64-bit DMA on this hardware is more trouble than it's | ||
| 2531 | * worth. It is far easier to limit to 32-bit DMA than update | ||
| 2532 | * various kernel subsystems to support the mechanics required by a | ||
| 2533 | * fixed-high-32-bit system. | ||
| 2534 | */ | ||
| 2535 | if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) || | ||
| 2536 | (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) { | ||
| 2537 | dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); | ||
| 2538 | goto err_dma; | ||
| 2539 | } | ||
| 2540 | |||
| 2541 | err = pci_request_regions(pdev, atl1c_driver_name); | ||
| 2542 | if (err) { | ||
| 2543 | dev_err(&pdev->dev, "cannot obtain PCI resources\n"); | ||
| 2544 | goto err_pci_reg; | ||
| 2545 | } | ||
| 2546 | |||
| 2547 | pci_set_master(pdev); | ||
| 2548 | |||
| 2549 | netdev = alloc_etherdev(sizeof(struct atl1c_adapter)); | ||
| 2550 | if (netdev == NULL) { | ||
| 2551 | err = -ENOMEM; | ||
| 2552 | dev_err(&pdev->dev, "etherdev alloc failed\n"); | ||
| 2553 | goto err_alloc_etherdev; | ||
| 2554 | } | ||
| 2555 | |||
| 2556 | err = atl1c_init_netdev(netdev, pdev); | ||
| 2557 | if (err) { | ||
| 2558 | dev_err(&pdev->dev, "init netdevice failed\n"); | ||
| 2559 | goto err_init_netdev; | ||
| 2560 | } | ||
| 2561 | adapter = netdev_priv(netdev); | ||
| 2562 | adapter->bd_number = cards_found; | ||
| 2563 | adapter->netdev = netdev; | ||
| 2564 | adapter->pdev = pdev; | ||
| 2565 | adapter->hw.adapter = adapter; | ||
| 2566 | adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg); | ||
| 2567 | adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); | ||
| 2568 | if (!adapter->hw.hw_addr) { | ||
| 2569 | err = -EIO; | ||
| 2570 | dev_err(&pdev->dev, "cannot map device registers\n"); | ||
| 2571 | goto err_ioremap; | ||
| 2572 | } | ||
| 2573 | netdev->base_addr = (unsigned long)adapter->hw.hw_addr; | ||
| 2574 | |||
| 2575 | /* init mii data */ | ||
| 2576 | adapter->mii.dev = netdev; | ||
| 2577 | adapter->mii.mdio_read = atl1c_mdio_read; | ||
| 2578 | adapter->mii.mdio_write = atl1c_mdio_write; | ||
| 2579 | adapter->mii.phy_id_mask = 0x1f; | ||
| 2580 | adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; | ||
| 2581 | netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); | ||
| 2582 | setup_timer(&adapter->phy_config_timer, atl1c_phy_config, | ||
| 2583 | (unsigned long)adapter); | ||
| 2584 | /* setup the private structure */ | ||
| 2585 | err = atl1c_sw_init(adapter); | ||
| 2586 | if (err) { | ||
| 2587 | dev_err(&pdev->dev, "net device private data init failed\n"); | ||
| 2588 | goto err_sw_init; | ||
| 2589 | } | ||
| 2590 | atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | | ||
| 2591 | ATL1C_PCIE_PHY_RESET); | ||
| 2592 | |||
| 2593 | /* Init GPHY as early as possible due to power saving issue */ | ||
| 2594 | atl1c_phy_reset(&adapter->hw); | ||
| 2595 | |||
| 2596 | err = atl1c_reset_mac(&adapter->hw); | ||
| 2597 | if (err) { | ||
| 2598 | err = -EIO; | ||
| 2599 | goto err_reset; | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | device_init_wakeup(&pdev->dev, 1); | ||
| 2603 | /* reset the controller to | ||
| 2604 | * put the device in a known good starting state */ | ||
| 2605 | err = atl1c_phy_init(&adapter->hw); | ||
| 2606 | if (err) { | ||
| 2607 | err = -EIO; | ||
| 2608 | goto err_reset; | ||
| 2609 | } | ||
| 2610 | if (atl1c_read_mac_addr(&adapter->hw) != 0) { | ||
| 2611 | err = -EIO; | ||
| 2612 | dev_err(&pdev->dev, "get mac address failed\n"); | ||
| 2613 | goto err_eeprom; | ||
| 2614 | } | ||
| 2615 | memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); | ||
| 2616 | memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); | ||
| 2617 | if (netif_msg_probe(adapter)) | ||
| 2618 | dev_dbg(&pdev->dev, | ||
| 2619 | "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n", | ||
| 2620 | adapter->hw.mac_addr[0], adapter->hw.mac_addr[1], | ||
| 2621 | adapter->hw.mac_addr[2], adapter->hw.mac_addr[3], | ||
| 2622 | adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); | ||
| 2623 | |||
| 2624 | atl1c_hw_set_mac_addr(&adapter->hw); | ||
| 2625 | INIT_WORK(&adapter->reset_task, atl1c_reset_task); | ||
| 2626 | INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); | ||
| 2627 | err = register_netdev(netdev); | ||
| 2628 | if (err) { | ||
| 2629 | dev_err(&pdev->dev, "register netdevice failed\n"); | ||
| 2630 | goto err_register; | ||
| 2631 | } | ||
| 2632 | |||
| 2633 | if (netif_msg_probe(adapter)) | ||
| 2634 | dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION); | ||
| 2635 | cards_found++; | ||
| 2636 | return 0; | ||
| 2637 | |||
| 2638 | err_reset: | ||
| 2639 | err_register: | ||
| 2640 | err_sw_init: | ||
| 2641 | err_eeprom: | ||
| 2642 | iounmap(adapter->hw.hw_addr); | ||
| 2643 | err_init_netdev: | ||
| 2644 | err_ioremap: | ||
| 2645 | free_netdev(netdev); | ||
| 2646 | err_alloc_etherdev: | ||
| 2647 | pci_release_regions(pdev); | ||
| 2648 | err_pci_reg: | ||
| 2649 | err_dma: | ||
| 2650 | pci_disable_device(pdev); | ||
| 2651 | return err; | ||
| 2652 | } | ||
| 2653 | |||
| 2654 | /* | ||
| 2655 | * atl1c_remove - Device Removal Routine | ||
| 2656 | * @pdev: PCI device information struct | ||
| 2657 | * | ||
| 2658 | * atl1c_remove is called by the PCI subsystem to alert the driver | ||
| 2659 | * that it should release a PCI device. The could be caused by a | ||
| 2660 | * Hot-Plug event, or because the driver is going to be removed from | ||
| 2661 | * memory. | ||
| 2662 | */ | ||
| 2663 | static void __devexit atl1c_remove(struct pci_dev *pdev) | ||
| 2664 | { | ||
| 2665 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2666 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2667 | |||
| 2668 | unregister_netdev(netdev); | ||
| 2669 | atl1c_phy_disable(&adapter->hw); | ||
| 2670 | |||
| 2671 | iounmap(adapter->hw.hw_addr); | ||
| 2672 | |||
| 2673 | pci_release_regions(pdev); | ||
| 2674 | pci_disable_device(pdev); | ||
| 2675 | free_netdev(netdev); | ||
| 2676 | } | ||
| 2677 | |||
| 2678 | /* | ||
| 2679 | * atl1c_io_error_detected - called when PCI error is detected | ||
| 2680 | * @pdev: Pointer to PCI device | ||
| 2681 | * @state: The current pci connection state | ||
| 2682 | * | ||
| 2683 | * This function is called after a PCI bus error affecting | ||
| 2684 | * this device has been detected. | ||
| 2685 | */ | ||
| 2686 | static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev, | ||
| 2687 | pci_channel_state_t state) | ||
| 2688 | { | ||
| 2689 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2690 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2691 | |||
| 2692 | netif_device_detach(netdev); | ||
| 2693 | |||
| 2694 | if (netif_running(netdev)) | ||
| 2695 | atl1c_down(adapter); | ||
| 2696 | |||
| 2697 | pci_disable_device(pdev); | ||
| 2698 | |||
| 2699 | /* Request a slot slot reset. */ | ||
| 2700 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | /* | ||
| 2704 | * atl1c_io_slot_reset - called after the pci bus has been reset. | ||
| 2705 | * @pdev: Pointer to PCI device | ||
| 2706 | * | ||
| 2707 | * Restart the card from scratch, as if from a cold-boot. Implementation | ||
| 2708 | * resembles the first-half of the e1000_resume routine. | ||
| 2709 | */ | ||
| 2710 | static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev) | ||
| 2711 | { | ||
| 2712 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2713 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2714 | |||
| 2715 | if (pci_enable_device(pdev)) { | ||
| 2716 | if (netif_msg_hw(adapter)) | ||
| 2717 | dev_err(&pdev->dev, | ||
| 2718 | "Cannot re-enable PCI device after reset\n"); | ||
| 2719 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 2720 | } | ||
| 2721 | pci_set_master(pdev); | ||
| 2722 | |||
| 2723 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
| 2724 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
| 2725 | |||
| 2726 | atl1c_reset_mac(&adapter->hw); | ||
| 2727 | |||
| 2728 | return PCI_ERS_RESULT_RECOVERED; | ||
| 2729 | } | ||
| 2730 | |||
| 2731 | /* | ||
| 2732 | * atl1c_io_resume - called when traffic can start flowing again. | ||
| 2733 | * @pdev: Pointer to PCI device | ||
| 2734 | * | ||
| 2735 | * This callback is called when the error recovery driver tells us that | ||
| 2736 | * its OK to resume normal operation. Implementation resembles the | ||
| 2737 | * second-half of the atl1c_resume routine. | ||
| 2738 | */ | ||
| 2739 | static void atl1c_io_resume(struct pci_dev *pdev) | ||
| 2740 | { | ||
| 2741 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 2742 | struct atl1c_adapter *adapter = netdev_priv(netdev); | ||
| 2743 | |||
| 2744 | if (netif_running(netdev)) { | ||
| 2745 | if (atl1c_up(adapter)) { | ||
| 2746 | if (netif_msg_hw(adapter)) | ||
| 2747 | dev_err(&pdev->dev, | ||
| 2748 | "Cannot bring device back up after reset\n"); | ||
| 2749 | return; | ||
| 2750 | } | ||
| 2751 | } | ||
| 2752 | |||
| 2753 | netif_device_attach(netdev); | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | static struct pci_error_handlers atl1c_err_handler = { | ||
| 2757 | .error_detected = atl1c_io_error_detected, | ||
| 2758 | .slot_reset = atl1c_io_slot_reset, | ||
| 2759 | .resume = atl1c_io_resume, | ||
| 2760 | }; | ||
| 2761 | |||
| 2762 | static struct pci_driver atl1c_driver = { | ||
| 2763 | .name = atl1c_driver_name, | ||
| 2764 | .id_table = atl1c_pci_tbl, | ||
| 2765 | .probe = atl1c_probe, | ||
| 2766 | .remove = __devexit_p(atl1c_remove), | ||
| 2767 | /* Power Managment Hooks */ | ||
| 2768 | .suspend = atl1c_suspend, | ||
| 2769 | .resume = atl1c_resume, | ||
| 2770 | .shutdown = atl1c_shutdown, | ||
| 2771 | .err_handler = &atl1c_err_handler | ||
| 2772 | }; | ||
| 2773 | |||
| 2774 | /* | ||
| 2775 | * atl1c_init_module - Driver Registration Routine | ||
| 2776 | * | ||
| 2777 | * atl1c_init_module is the first routine called when the driver is | ||
| 2778 | * loaded. All it does is register with the PCI subsystem. | ||
| 2779 | */ | ||
| 2780 | static int __init atl1c_init_module(void) | ||
| 2781 | { | ||
| 2782 | return pci_register_driver(&atl1c_driver); | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | /* | ||
| 2786 | * atl1c_exit_module - Driver Exit Cleanup Routine | ||
| 2787 | * | ||
| 2788 | * atl1c_exit_module is called just before the driver is removed | ||
| 2789 | * from memory. | ||
| 2790 | */ | ||
| 2791 | static void __exit atl1c_exit_module(void) | ||
| 2792 | { | ||
| 2793 | pci_unregister_driver(&atl1c_driver); | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | module_init(atl1c_init_module); | ||
| 2797 | module_exit(atl1c_exit_module); | ||
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c38512ebcea..dc5f051005f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
| @@ -1264,8 +1264,14 @@ static void b44_clear_stats(struct b44 *bp) | |||
| 1264 | static void b44_chip_reset(struct b44 *bp, int reset_kind) | 1264 | static void b44_chip_reset(struct b44 *bp, int reset_kind) |
| 1265 | { | 1265 | { |
| 1266 | struct ssb_device *sdev = bp->sdev; | 1266 | struct ssb_device *sdev = bp->sdev; |
| 1267 | bool was_enabled; | ||
| 1267 | 1268 | ||
| 1268 | if (ssb_device_is_enabled(bp->sdev)) { | 1269 | was_enabled = ssb_device_is_enabled(bp->sdev); |
| 1270 | |||
| 1271 | ssb_device_enable(bp->sdev, 0); | ||
| 1272 | ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); | ||
| 1273 | |||
| 1274 | if (was_enabled) { | ||
| 1269 | bw32(bp, B44_RCV_LAZY, 0); | 1275 | bw32(bp, B44_RCV_LAZY, 0); |
| 1270 | bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); | 1276 | bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); |
| 1271 | b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); | 1277 | b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); |
| @@ -1277,10 +1283,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind) | |||
| 1277 | } | 1283 | } |
| 1278 | bw32(bp, B44_DMARX_CTRL, 0); | 1284 | bw32(bp, B44_DMARX_CTRL, 0); |
| 1279 | bp->rx_prod = bp->rx_cons = 0; | 1285 | bp->rx_prod = bp->rx_cons = 0; |
| 1280 | } else | 1286 | } |
| 1281 | ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); | ||
| 1282 | 1287 | ||
| 1283 | ssb_device_enable(bp->sdev, 0); | ||
| 1284 | b44_clear_stats(bp); | 1288 | b44_clear_stats(bp); |
| 1285 | 1289 | ||
| 1286 | /* | 1290 | /* |
| @@ -2236,6 +2240,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev) | |||
| 2236 | struct net_device *dev = ssb_get_drvdata(sdev); | 2240 | struct net_device *dev = ssb_get_drvdata(sdev); |
| 2237 | 2241 | ||
| 2238 | unregister_netdev(dev); | 2242 | unregister_netdev(dev); |
| 2243 | ssb_device_disable(sdev, 0); | ||
| 2239 | ssb_bus_may_powerdown(sdev->bus); | 2244 | ssb_bus_may_powerdown(sdev->bus); |
| 2240 | free_netdev(dev); | 2245 | free_netdev(dev); |
| 2241 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); | 2246 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 0089746b8d0..bab8a934c33 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -90,6 +90,7 @@ static const struct pci_device_id cxgb3_pci_tbl[] = { | |||
| 90 | CH_DEVICE(0x30, 2), /* T3B10 */ | 90 | CH_DEVICE(0x30, 2), /* T3B10 */ |
| 91 | CH_DEVICE(0x31, 3), /* T3B20 */ | 91 | CH_DEVICE(0x31, 3), /* T3B20 */ |
| 92 | CH_DEVICE(0x32, 1), /* T3B02 */ | 92 | CH_DEVICE(0x32, 1), /* T3B02 */ |
| 93 | CH_DEVICE(0x35, 6), /* T3C20-derived T3C10 */ | ||
| 93 | {0,} | 94 | {0,} |
| 94 | }; | 95 | }; |
| 95 | 96 | ||
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 2d1433077a8..ac2a974dfe3 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
| @@ -512,6 +512,13 @@ static const struct adapter_info t3_adap_info[] = { | |||
| 512 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, | 512 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, |
| 513 | { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | 513 | { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, |
| 514 | &mi1_mdio_ext_ops, "Chelsio T320"}, | 514 | &mi1_mdio_ext_ops, "Chelsio T320"}, |
| 515 | {}, | ||
| 516 | {}, | ||
| 517 | {1, 0, | ||
| 518 | F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN | | ||
| 519 | F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, | ||
| 520 | { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | ||
| 521 | &mi1_mdio_ext_ops, "Chelsio T310" }, | ||
| 515 | }; | 522 | }; |
| 516 | 523 | ||
| 517 | /* | 524 | /* |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 5b910cf6374..b8251e82705 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -6011,9 +6011,20 @@ static void nv_shutdown(struct pci_dev *pdev) | |||
| 6011 | if (netif_running(dev)) | 6011 | if (netif_running(dev)) |
| 6012 | nv_close(dev); | 6012 | nv_close(dev); |
| 6013 | 6013 | ||
| 6014 | nv_restore_mac_addr(pdev); | 6014 | /* |
| 6015 | * Restore the MAC so a kernel started by kexec won't get confused. | ||
| 6016 | * If we really go for poweroff, we must not restore the MAC, | ||
| 6017 | * otherwise the MAC for WOL will be reversed at least on some boards. | ||
| 6018 | */ | ||
| 6019 | if (system_state != SYSTEM_POWER_OFF) { | ||
| 6020 | nv_restore_mac_addr(pdev); | ||
| 6021 | } | ||
| 6015 | 6022 | ||
| 6016 | pci_disable_device(pdev); | 6023 | pci_disable_device(pdev); |
| 6024 | /* | ||
| 6025 | * Apparently it is not possible to reinitialise from D3 hot, | ||
| 6026 | * only put the device into D3 if we really go for poweroff. | ||
| 6027 | */ | ||
| 6017 | if (system_state == SYSTEM_POWER_OFF) { | 6028 | if (system_state == SYSTEM_POWER_OFF) { |
| 6018 | if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) | 6029 | if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) |
| 6019 | pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); | 6030 | pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9b12a13a640..9831b3f408a 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -1284,7 +1284,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1284 | spin_lock_irqsave(&priv->txlock, flags); | 1284 | spin_lock_irqsave(&priv->txlock, flags); |
| 1285 | 1285 | ||
| 1286 | /* check if there is space to queue this packet */ | 1286 | /* check if there is space to queue this packet */ |
| 1287 | if (nr_frags > priv->num_txbdfree) { | 1287 | if ((nr_frags+1) > priv->num_txbdfree) { |
| 1288 | /* no space, stop the queue */ | 1288 | /* no space, stop the queue */ |
| 1289 | netif_stop_queue(dev); | 1289 | netif_stop_queue(dev); |
| 1290 | dev->stats.tx_fifo_errors++; | 1290 | dev->stats.tx_fifo_errors++; |
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 5e070f44663..0486cbe01ad 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c | |||
| @@ -467,7 +467,7 @@ init_module(void) | |||
| 467 | if (this_dev != 0) break; /* only autoprobe 1st one */ | 467 | if (this_dev != 0) break; /* only autoprobe 1st one */ |
| 468 | printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); | 468 | printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); |
| 469 | } | 469 | } |
| 470 | dev = alloc_ei_netdev(); | 470 | dev = alloc_eip_netdev(); |
| 471 | if (!dev) | 471 | if (!dev) |
| 472 | break; | 472 | break; |
| 473 | dev->irq = irq[this_dev]; | 473 | dev->irq = irq[this_dev]; |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 5f31bbb614a..13f11f402a9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) | |||
| 1175 | { | 1175 | { |
| 1176 | struct mib_counters *p = &mp->mib_counters; | 1176 | struct mib_counters *p = &mp->mib_counters; |
| 1177 | 1177 | ||
| 1178 | spin_lock(&mp->mib_counters_lock); | 1178 | spin_lock_bh(&mp->mib_counters_lock); |
| 1179 | p->good_octets_received += mib_read(mp, 0x00); | 1179 | p->good_octets_received += mib_read(mp, 0x00); |
| 1180 | p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; | 1180 | p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; |
| 1181 | p->bad_octets_received += mib_read(mp, 0x08); | 1181 | p->bad_octets_received += mib_read(mp, 0x08); |
| @@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) | |||
| 1208 | p->bad_crc_event += mib_read(mp, 0x74); | 1208 | p->bad_crc_event += mib_read(mp, 0x74); |
| 1209 | p->collision += mib_read(mp, 0x78); | 1209 | p->collision += mib_read(mp, 0x78); |
| 1210 | p->late_collision += mib_read(mp, 0x7c); | 1210 | p->late_collision += mib_read(mp, 0x7c); |
| 1211 | spin_unlock(&mp->mib_counters_lock); | 1211 | spin_unlock_bh(&mp->mib_counters_lock); |
| 1212 | 1212 | ||
| 1213 | mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); | 1213 | mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); |
| 1214 | } | 1214 | } |
| @@ -1575,7 +1575,7 @@ oom: | |||
| 1575 | return; | 1575 | return; |
| 1576 | } | 1576 | } |
| 1577 | 1577 | ||
| 1578 | mc_spec = kmalloc(0x200, GFP_KERNEL); | 1578 | mc_spec = kmalloc(0x200, GFP_ATOMIC); |
| 1579 | if (mc_spec == NULL) | 1579 | if (mc_spec == NULL) |
| 1580 | goto oom; | 1580 | goto oom; |
| 1581 | mc_other = mc_spec + (0x100 >> 2); | 1581 | mc_other = mc_spec + (0x100 >> 2); |
| @@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev) | |||
| 2216 | wrlp(mp, INT_MASK, 0x00000000); | 2216 | wrlp(mp, INT_MASK, 0x00000000); |
| 2217 | rdlp(mp, INT_MASK); | 2217 | rdlp(mp, INT_MASK); |
| 2218 | 2218 | ||
| 2219 | del_timer_sync(&mp->mib_counters_timer); | ||
| 2220 | |||
| 2221 | napi_disable(&mp->napi); | 2219 | napi_disable(&mp->napi); |
| 2222 | 2220 | ||
| 2223 | del_timer_sync(&mp->rx_oom); | 2221 | del_timer_sync(&mp->rx_oom); |
| @@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev) | |||
| 2229 | port_reset(mp); | 2227 | port_reset(mp); |
| 2230 | mv643xx_eth_get_stats(dev); | 2228 | mv643xx_eth_get_stats(dev); |
| 2231 | mib_counters_update(mp); | 2229 | mib_counters_update(mp); |
| 2230 | del_timer_sync(&mp->mib_counters_timer); | ||
| 2232 | 2231 | ||
| 2233 | skb_queue_purge(&mp->rx_recycle); | 2232 | skb_queue_purge(&mp->rx_recycle); |
| 2234 | 2233 | ||
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9f33e442f40..13087782ac4 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
| @@ -588,7 +588,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 588 | adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; | 588 | adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; |
| 589 | adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; | 589 | adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; |
| 590 | 590 | ||
| 591 | mem_ptr0 = ioremap(mem_base, mem_len); | 591 | mem_ptr0 = pci_ioremap_bar(pdev, 0); |
| 592 | if (mem_ptr0 == NULL) { | ||
| 593 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); | ||
| 594 | return -EIO; | ||
| 595 | } | ||
| 596 | |||
| 592 | pci_len0 = mem_len; | 597 | pci_len0 = mem_len; |
| 593 | first_page_group_start = 0; | 598 | first_page_group_start = 0; |
| 594 | first_page_group_end = 0; | 599 | first_page_group_end = 0; |
| @@ -795,9 +800,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 795 | * See if the firmware gave us a virtual-physical port mapping. | 800 | * See if the firmware gave us a virtual-physical port mapping. |
| 796 | */ | 801 | */ |
| 797 | adapter->physical_port = adapter->portnum; | 802 | adapter->physical_port = adapter->portnum; |
| 798 | i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum)); | 803 | if (adapter->fw_major < 4) { |
| 799 | if (i != 0x55555555) | 804 | i = adapter->pci_read_normalize(adapter, |
| 800 | adapter->physical_port = i; | 805 | CRB_V2P(adapter->portnum)); |
| 806 | if (i != 0x55555555) | ||
| 807 | adapter->physical_port = i; | ||
| 808 | } | ||
| 801 | 809 | ||
| 802 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); | 810 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); |
| 803 | 811 | ||
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0771eb6fc6e..b3473401c83 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32; | |||
| 81 | #define RTL8169_TX_TIMEOUT (6*HZ) | 81 | #define RTL8169_TX_TIMEOUT (6*HZ) |
| 82 | #define RTL8169_PHY_TIMEOUT (10*HZ) | 82 | #define RTL8169_PHY_TIMEOUT (10*HZ) |
| 83 | 83 | ||
| 84 | #define RTL_EEPROM_SIG cpu_to_le32(0x8129) | 84 | #define RTL_EEPROM_SIG 0x8129 |
| 85 | #define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) | ||
| 86 | #define RTL_EEPROM_SIG_ADDR 0x0000 | 85 | #define RTL_EEPROM_SIG_ADDR 0x0000 |
| 86 | #define RTL_EEPROM_MAC_ADDR 0x0007 | ||
| 87 | 87 | ||
| 88 | /* write/read MMIO register */ | 88 | /* write/read MMIO register */ |
| 89 | #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) | 89 | #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) |
| @@ -293,6 +293,11 @@ enum rtl_register_content { | |||
| 293 | /* Cfg9346Bits */ | 293 | /* Cfg9346Bits */ |
| 294 | Cfg9346_Lock = 0x00, | 294 | Cfg9346_Lock = 0x00, |
| 295 | Cfg9346_Unlock = 0xc0, | 295 | Cfg9346_Unlock = 0xc0, |
| 296 | Cfg9346_Program = 0x80, /* Programming mode */ | ||
| 297 | Cfg9346_EECS = 0x08, /* Chip select */ | ||
| 298 | Cfg9346_EESK = 0x04, /* Serial data clock */ | ||
| 299 | Cfg9346_EEDI = 0x02, /* Data input */ | ||
| 300 | Cfg9346_EEDO = 0x01, /* Data output */ | ||
| 296 | 301 | ||
| 297 | /* rx_mode_bits */ | 302 | /* rx_mode_bits */ |
| 298 | AcceptErr = 0x20, | 303 | AcceptErr = 0x20, |
| @@ -305,6 +310,7 @@ enum rtl_register_content { | |||
| 305 | /* RxConfigBits */ | 310 | /* RxConfigBits */ |
| 306 | RxCfgFIFOShift = 13, | 311 | RxCfgFIFOShift = 13, |
| 307 | RxCfgDMAShift = 8, | 312 | RxCfgDMAShift = 8, |
| 313 | RxCfg9356SEL = 6, /* EEPROM type: 0 = 9346, 1 = 9356 */ | ||
| 308 | 314 | ||
| 309 | /* TxConfigBits */ | 315 | /* TxConfigBits */ |
| 310 | TxInterFrameGapShift = 24, | 316 | TxInterFrameGapShift = 24, |
| @@ -1963,6 +1969,108 @@ static const struct net_device_ops rtl8169_netdev_ops = { | |||
| 1963 | 1969 | ||
| 1964 | }; | 1970 | }; |
| 1965 | 1971 | ||
| 1972 | /* Delay between EEPROM clock transitions. Force out buffered PCI writes. */ | ||
| 1973 | #define RTL_EEPROM_DELAY() RTL_R8(Cfg9346) | ||
| 1974 | #define RTL_EEPROM_READ_CMD 6 | ||
| 1975 | |||
| 1976 | /* read 16bit word stored in EEPROM. EEPROM is addressed by words. */ | ||
| 1977 | static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr) | ||
| 1978 | { | ||
| 1979 | u16 result = 0; | ||
| 1980 | int cmd, cmd_len, i; | ||
| 1981 | |||
| 1982 | /* check for EEPROM address size (in bits) */ | ||
| 1983 | if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) { | ||
| 1984 | /* EEPROM is 93C56 */ | ||
| 1985 | cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */ | ||
| 1986 | cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff); | ||
| 1987 | } else { | ||
| 1988 | /* EEPROM is 93C46 */ | ||
| 1989 | cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */ | ||
| 1990 | cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f); | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | /* enter programming mode */ | ||
| 1994 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 1995 | RTL_EEPROM_DELAY(); | ||
| 1996 | |||
| 1997 | /* write command and requested address */ | ||
| 1998 | while (cmd_len--) { | ||
| 1999 | u8 x = Cfg9346_Program | Cfg9346_EECS; | ||
| 2000 | |||
| 2001 | x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0; | ||
| 2002 | |||
| 2003 | /* write a bit */ | ||
| 2004 | RTL_W8(Cfg9346, x); | ||
| 2005 | RTL_EEPROM_DELAY(); | ||
| 2006 | |||
| 2007 | /* raise clock */ | ||
| 2008 | RTL_W8(Cfg9346, x | Cfg9346_EESK); | ||
| 2009 | RTL_EEPROM_DELAY(); | ||
| 2010 | } | ||
| 2011 | |||
| 2012 | /* lower clock */ | ||
| 2013 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 2014 | RTL_EEPROM_DELAY(); | ||
| 2015 | |||
| 2016 | /* read back 16bit value */ | ||
| 2017 | for (i = 16; i > 0; i--) { | ||
| 2018 | /* raise clock */ | ||
| 2019 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK); | ||
| 2020 | RTL_EEPROM_DELAY(); | ||
| 2021 | |||
| 2022 | result <<= 1; | ||
| 2023 | result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0; | ||
| 2024 | |||
| 2025 | /* lower clock */ | ||
| 2026 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 2027 | RTL_EEPROM_DELAY(); | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | RTL_W8(Cfg9346, Cfg9346_Program); | ||
| 2031 | /* leave programming mode */ | ||
| 2032 | RTL_W8(Cfg9346, Cfg9346_Lock); | ||
| 2033 | |||
| 2034 | return result; | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | static void rtl_init_mac_address(struct rtl8169_private *tp, | ||
| 2038 | void __iomem *ioaddr) | ||
| 2039 | { | ||
| 2040 | struct pci_dev *pdev = tp->pci_dev; | ||
| 2041 | u16 x; | ||
| 2042 | u8 mac[8]; | ||
| 2043 | |||
| 2044 | /* read EEPROM signature */ | ||
| 2045 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR); | ||
| 2046 | |||
| 2047 | if (x != RTL_EEPROM_SIG) { | ||
| 2048 | dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x); | ||
| 2049 | return; | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | /* read MAC address */ | ||
| 2053 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR); | ||
| 2054 | mac[0] = x & 0xff; | ||
| 2055 | mac[1] = x >> 8; | ||
| 2056 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1); | ||
| 2057 | mac[2] = x & 0xff; | ||
| 2058 | mac[3] = x >> 8; | ||
| 2059 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2); | ||
| 2060 | mac[4] = x & 0xff; | ||
| 2061 | mac[5] = x >> 8; | ||
| 2062 | |||
| 2063 | if (netif_msg_probe(tp)) { | ||
| 2064 | DECLARE_MAC_BUF(buf); | ||
| 2065 | |||
| 2066 | dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n", | ||
| 2067 | print_mac(buf, mac)); | ||
| 2068 | } | ||
| 2069 | |||
| 2070 | if (is_valid_ether_addr(mac)) | ||
| 2071 | rtl_rar_set(tp, mac); | ||
| 2072 | } | ||
| 2073 | |||
| 1966 | static int __devinit | 2074 | static int __devinit |
| 1967 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2075 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 1968 | { | 2076 | { |
| @@ -2141,6 +2249,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2141 | 2249 | ||
| 2142 | tp->mmio_addr = ioaddr; | 2250 | tp->mmio_addr = ioaddr; |
| 2143 | 2251 | ||
| 2252 | rtl_init_mac_address(tp, ioaddr); | ||
| 2253 | |||
| 2144 | /* Get MAC address */ | 2254 | /* Get MAC address */ |
| 2145 | for (i = 0; i < MAC_ADDR_LEN; i++) | 2255 | for (i = 0; i < MAC_ADDR_LEN; i++) |
| 2146 | dev->dev_addr[i] = RTL_R8(MAC0 + i); | 2256 | dev->dev_addr[i] = RTL_R8(MAC0 + i); |
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 783c1a7b869..9a78daec2fe 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
| @@ -1624,7 +1624,7 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op) | |||
| 1624 | do { | 1624 | do { |
| 1625 | msleep(1); | 1625 | msleep(1); |
| 1626 | e2cmd = smsc911x_reg_read(pdata, E2P_CMD); | 1626 | e2cmd = smsc911x_reg_read(pdata, E2P_CMD); |
| 1627 | } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); | 1627 | } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout)); |
| 1628 | 1628 | ||
| 1629 | if (!timeout) { | 1629 | if (!timeout) { |
| 1630 | SMSC_TRACE(DRV, "TIMED OUT"); | 1630 | SMSC_TRACE(DRV, "TIMED OUT"); |
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index a1e4b3895b3..4e15ae068b3 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c | |||
| @@ -341,7 +341,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op) | |||
| 341 | do { | 341 | do { |
| 342 | msleep(1); | 342 | msleep(1); |
| 343 | e2cmd = smsc9420_reg_read(pd, E2P_CMD); | 343 | e2cmd = smsc9420_reg_read(pd, E2P_CMD); |
| 344 | } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); | 344 | } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout)); |
| 345 | 345 | ||
| 346 | if (!timeout) { | 346 | if (!timeout) { |
| 347 | smsc_info(HW, "TIMED OUT"); | 347 | smsc_info(HW, "TIMED OUT"); |
| @@ -413,6 +413,7 @@ static int smsc9420_ethtool_get_eeprom(struct net_device *dev, | |||
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | memcpy(data, &eeprom_data[eeprom->offset], len); | 415 | memcpy(data, &eeprom_data[eeprom->offset], len); |
| 416 | eeprom->magic = SMSC9420_EEPROM_MAGIC; | ||
| 416 | eeprom->len = len; | 417 | eeprom->len = len; |
| 417 | return 0; | 418 | return 0; |
| 418 | } | 419 | } |
| @@ -423,6 +424,9 @@ static int smsc9420_ethtool_set_eeprom(struct net_device *dev, | |||
| 423 | struct smsc9420_pdata *pd = netdev_priv(dev); | 424 | struct smsc9420_pdata *pd = netdev_priv(dev); |
| 424 | int ret; | 425 | int ret; |
| 425 | 426 | ||
| 427 | if (eeprom->magic != SMSC9420_EEPROM_MAGIC) | ||
| 428 | return -EINVAL; | ||
| 429 | |||
| 426 | smsc9420_eeprom_enable_access(pd); | 430 | smsc9420_eeprom_enable_access(pd); |
| 427 | smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_); | 431 | smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_); |
| 428 | ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data); | 432 | ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data); |
diff --git a/drivers/net/smsc9420.h b/drivers/net/smsc9420.h index 69c351f93f8..e441402f77a 100644 --- a/drivers/net/smsc9420.h +++ b/drivers/net/smsc9420.h | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #define LAN_REGISTER_EXTENT (0x400) | 44 | #define LAN_REGISTER_EXTENT (0x400) |
| 45 | 45 | ||
| 46 | #define SMSC9420_EEPROM_SIZE ((u32)11) | 46 | #define SMSC9420_EEPROM_SIZE ((u32)11) |
| 47 | #define SMSC9420_EEPROM_MAGIC (0x9420) | ||
| 47 | 48 | ||
| 48 | #define PKT_BUF_SZ (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4) | 49 | #define PKT_BUF_SZ (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4) |
| 49 | 50 | ||
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index feaf0e0577d..43695b76606 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c | |||
| @@ -909,7 +909,7 @@ static void check_duplex(struct net_device *dev) | |||
| 909 | printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " | 909 | printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " |
| 910 | "negotiated capability %4.4x.\n", dev->name, | 910 | "negotiated capability %4.4x.\n", dev->name, |
| 911 | duplex ? "full" : "half", np->phys[0], negotiated); | 911 | duplex ? "full" : "half", np->phys[0], negotiated); |
| 912 | iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0); | 912 | iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0); |
| 913 | } | 913 | } |
| 914 | } | 914 | } |
| 915 | 915 | ||
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 49187634106..8d64b1da046 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
| @@ -1157,7 +1157,7 @@ static void gem_pcs_reset(struct gem *gp) | |||
| 1157 | if (limit-- <= 0) | 1157 | if (limit-- <= 0) |
| 1158 | break; | 1158 | break; |
| 1159 | } | 1159 | } |
| 1160 | if (limit <= 0) | 1160 | if (limit < 0) |
| 1161 | printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", | 1161 | printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", |
| 1162 | gp->dev->name); | 1162 | gp->dev->name); |
| 1163 | } | 1163 | } |
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 28137328175..16c528db725 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
| @@ -343,7 +343,7 @@ static void lance_init_ring_dvma(struct net_device *dev) | |||
| 343 | ib->phys_addr [5] = dev->dev_addr [4]; | 343 | ib->phys_addr [5] = dev->dev_addr [4]; |
| 344 | 344 | ||
| 345 | /* Setup the Tx ring entries */ | 345 | /* Setup the Tx ring entries */ |
| 346 | for (i = 0; i <= TX_RING_SIZE; i++) { | 346 | for (i = 0; i < TX_RING_SIZE; i++) { |
| 347 | leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i)); | 347 | leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i)); |
| 348 | ib->btx_ring [i].tmd0 = leptr; | 348 | ib->btx_ring [i].tmd0 = leptr; |
| 349 | ib->btx_ring [i].tmd1_hadr = leptr >> 16; | 349 | ib->btx_ring [i].tmd1_hadr = leptr >> 16; |
| @@ -399,7 +399,7 @@ static void lance_init_ring_pio(struct net_device *dev) | |||
| 399 | sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]); | 399 | sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]); |
| 400 | 400 | ||
| 401 | /* Setup the Tx ring entries */ | 401 | /* Setup the Tx ring entries */ |
| 402 | for (i = 0; i <= TX_RING_SIZE; i++) { | 402 | for (i = 0; i < TX_RING_SIZE; i++) { |
| 403 | leptr = libbuff_offset(tx_buf, i); | 403 | leptr = libbuff_offset(tx_buf, i); |
| 404 | sbus_writew(leptr, &ib->btx_ring [i].tmd0); | 404 | sbus_writew(leptr, &ib->btx_ring [i].tmd0); |
| 405 | sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr); | 405 | sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr); |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4595962fb8e..b080f9493d8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -2237,8 +2237,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
| 2237 | phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask; | 2237 | phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask; |
| 2238 | if (phyid != TG3_PHY_ID_BCMAC131) { | 2238 | if (phyid != TG3_PHY_ID_BCMAC131) { |
| 2239 | phyid &= TG3_PHY_OUI_MASK; | 2239 | phyid &= TG3_PHY_OUI_MASK; |
| 2240 | if (phyid == TG3_PHY_OUI_1 && | 2240 | if (phyid == TG3_PHY_OUI_1 || |
| 2241 | phyid == TG3_PHY_OUI_2 && | 2241 | phyid == TG3_PHY_OUI_2 || |
| 2242 | phyid == TG3_PHY_OUI_3) | 2242 | phyid == TG3_PHY_OUI_3) |
| 2243 | do_low_power = true; | 2243 | do_low_power = true; |
| 2244 | } | 2244 | } |
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e009481c606..396f821b5ff 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
| @@ -1451,6 +1451,14 @@ static const struct usb_device_id products [] = { | |||
| 1451 | // Cables-to-Go USB Ethernet Adapter | 1451 | // Cables-to-Go USB Ethernet Adapter |
| 1452 | USB_DEVICE(0x0b95, 0x772a), | 1452 | USB_DEVICE(0x0b95, 0x772a), |
| 1453 | .driver_info = (unsigned long) &ax88772_info, | 1453 | .driver_info = (unsigned long) &ax88772_info, |
| 1454 | }, { | ||
| 1455 | // ABOCOM for pci | ||
| 1456 | USB_DEVICE(0x14ea, 0xab11), | ||
| 1457 | .driver_info = (unsigned long) &ax88178_info, | ||
| 1458 | }, { | ||
| 1459 | // ASIX 88772a | ||
| 1460 | USB_DEVICE(0x0db0, 0xa877), | ||
| 1461 | .driver_info = (unsigned long) &ax88772_info, | ||
| 1454 | }, | 1462 | }, |
| 1455 | { }, // END | 1463 | { }, // END |
| 1456 | }; | 1464 | }; |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 0e061dfea78..55e8ecc3a9e 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -559,6 +559,11 @@ static const struct usb_device_id products [] = { | |||
| 559 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, | 559 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, |
| 560 | USB_CDC_PROTO_NONE), | 560 | USB_CDC_PROTO_NONE), |
| 561 | .driver_info = (unsigned long) &cdc_info, | 561 | .driver_info = (unsigned long) &cdc_info, |
| 562 | }, { | ||
| 563 | /* Ericsson F3507g */ | ||
| 564 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, | ||
| 565 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 566 | .driver_info = (unsigned long) &cdc_info, | ||
| 562 | }, | 567 | }, |
| 563 | { }, // END | 568 | { }, // END |
| 564 | }; | 569 | }; |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index aa314907888..c32284ff3f5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -723,8 +723,8 @@ u32 usbnet_get_link (struct net_device *net) | |||
| 723 | if (dev->mii.mdio_read) | 723 | if (dev->mii.mdio_read) |
| 724 | return mii_link_ok(&dev->mii); | 724 | return mii_link_ok(&dev->mii); |
| 725 | 725 | ||
| 726 | /* Otherwise, say we're up (to avoid breaking scripts) */ | 726 | /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */ |
| 727 | return 1; | 727 | return ethtool_op_get_link(net); |
| 728 | } | 728 | } |
| 729 | EXPORT_SYMBOL_GPL(usbnet_get_link); | 729 | EXPORT_SYMBOL_GPL(usbnet_get_link); |
| 730 | 730 | ||
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index e24f7b3ace4..04882c8f9bf 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c | |||
| @@ -341,6 +341,11 @@ static const struct usb_device_id products [] = { | |||
| 341 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, | 341 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, |
| 342 | USB_CDC_PROTO_NONE), | 342 | USB_CDC_PROTO_NONE), |
| 343 | .driver_info = (unsigned long) &bogus_mdlm_info, | 343 | .driver_info = (unsigned long) &bogus_mdlm_info, |
| 344 | }, { | ||
| 345 | /* Motorola MOTOMAGX phones */ | ||
| 346 | USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, | ||
| 347 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 348 | .driver_info = (unsigned long) &bogus_mdlm_info, | ||
| 344 | }, | 349 | }, |
| 345 | 350 | ||
| 346 | /* Olympus has some models with a Zaurus-compatible option. | 351 | /* Olympus has some models with a Zaurus-compatible option. |
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 852d0e7c4e6..124fe75b8a8 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -239,6 +239,16 @@ static int veth_open(struct net_device *dev) | |||
| 239 | return 0; | 239 | return 0; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | static int veth_close(struct net_device *dev) | ||
| 243 | { | ||
| 244 | struct veth_priv *priv = netdev_priv(dev); | ||
| 245 | |||
| 246 | netif_carrier_off(dev); | ||
| 247 | netif_carrier_off(priv->peer); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 242 | static int veth_dev_init(struct net_device *dev) | 252 | static int veth_dev_init(struct net_device *dev) |
| 243 | { | 253 | { |
| 244 | struct veth_net_stats *stats; | 254 | struct veth_net_stats *stats; |
| @@ -263,10 +273,12 @@ static void veth_dev_free(struct net_device *dev) | |||
| 263 | } | 273 | } |
| 264 | 274 | ||
| 265 | static const struct net_device_ops veth_netdev_ops = { | 275 | static const struct net_device_ops veth_netdev_ops = { |
| 266 | .ndo_init = veth_dev_init, | 276 | .ndo_init = veth_dev_init, |
| 267 | .ndo_open = veth_open, | 277 | .ndo_open = veth_open, |
| 268 | .ndo_start_xmit = veth_xmit, | 278 | .ndo_stop = veth_close, |
| 269 | .ndo_get_stats = veth_get_stats, | 279 | .ndo_start_xmit = veth_xmit, |
| 280 | .ndo_get_stats = veth_get_stats, | ||
| 281 | .ndo_set_mac_address = eth_mac_addr, | ||
| 270 | }; | 282 | }; |
| 271 | 283 | ||
| 272 | static void veth_setup(struct net_device *dev) | 284 | static void veth_setup(struct net_device *dev) |
| @@ -279,44 +291,6 @@ static void veth_setup(struct net_device *dev) | |||
| 279 | dev->destructor = veth_dev_free; | 291 | dev->destructor = veth_dev_free; |
| 280 | } | 292 | } |
| 281 | 293 | ||
| 282 | static void veth_change_state(struct net_device *dev) | ||
| 283 | { | ||
| 284 | struct net_device *peer; | ||
| 285 | struct veth_priv *priv; | ||
| 286 | |||
| 287 | priv = netdev_priv(dev); | ||
| 288 | peer = priv->peer; | ||
| 289 | |||
| 290 | if (netif_carrier_ok(peer)) { | ||
| 291 | if (!netif_carrier_ok(dev)) | ||
| 292 | netif_carrier_on(dev); | ||
| 293 | } else { | ||
| 294 | if (netif_carrier_ok(dev)) | ||
| 295 | netif_carrier_off(dev); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | static int veth_device_event(struct notifier_block *unused, | ||
| 300 | unsigned long event, void *ptr) | ||
| 301 | { | ||
| 302 | struct net_device *dev = ptr; | ||
| 303 | |||
| 304 | if (dev->netdev_ops->ndo_open != veth_open) | ||
| 305 | goto out; | ||
| 306 | |||
| 307 | switch (event) { | ||
| 308 | case NETDEV_CHANGE: | ||
| 309 | veth_change_state(dev); | ||
| 310 | break; | ||
| 311 | } | ||
| 312 | out: | ||
| 313 | return NOTIFY_DONE; | ||
| 314 | } | ||
| 315 | |||
| 316 | static struct notifier_block veth_notifier_block __read_mostly = { | ||
| 317 | .notifier_call = veth_device_event, | ||
| 318 | }; | ||
| 319 | |||
| 320 | /* | 294 | /* |
| 321 | * netlink interface | 295 | * netlink interface |
| 322 | */ | 296 | */ |
| @@ -467,14 +441,12 @@ static struct rtnl_link_ops veth_link_ops = { | |||
| 467 | 441 | ||
| 468 | static __init int veth_init(void) | 442 | static __init int veth_init(void) |
| 469 | { | 443 | { |
| 470 | register_netdevice_notifier(&veth_notifier_block); | ||
| 471 | return rtnl_link_register(&veth_link_ops); | 444 | return rtnl_link_register(&veth_link_ops); |
| 472 | } | 445 | } |
| 473 | 446 | ||
| 474 | static __exit void veth_exit(void) | 447 | static __exit void veth_exit(void) |
| 475 | { | 448 | { |
| 476 | rtnl_link_unregister(&veth_link_ops); | 449 | rtnl_link_unregister(&veth_link_ops); |
| 477 | unregister_netdevice_notifier(&veth_notifier_block); | ||
| 478 | } | 450 | } |
| 479 | 451 | ||
| 480 | module_init(veth_init); | 452 | module_init(veth_init); |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 067c871cc22..3b9d27ea295 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
| @@ -157,7 +157,7 @@ enum { | |||
| 157 | 157 | ||
| 158 | 158 | ||
| 159 | /* Firmware version we request when pulling the fw image file */ | 159 | /* Firmware version we request when pulling the fw image file */ |
| 160 | #define I2400M_FW_VERSION "1.3" | 160 | #define I2400M_FW_VERSION "1.4" |
| 161 | 161 | ||
| 162 | 162 | ||
| 163 | /** | 163 | /** |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 727f067aca4..0e80990d8e8 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
| @@ -1538,6 +1538,7 @@ bad2: | |||
| 1538 | bad: | 1538 | bad: |
| 1539 | if (ah) | 1539 | if (ah) |
| 1540 | ath9k_hw_detach(ah); | 1540 | ath9k_hw_detach(ah); |
| 1541 | ath9k_exit_debug(sc); | ||
| 1541 | 1542 | ||
| 1542 | return error; | 1543 | return error; |
| 1543 | } | 1544 | } |
| @@ -1545,7 +1546,7 @@ bad: | |||
| 1545 | static int ath_attach(u16 devid, struct ath_softc *sc) | 1546 | static int ath_attach(u16 devid, struct ath_softc *sc) |
| 1546 | { | 1547 | { |
| 1547 | struct ieee80211_hw *hw = sc->hw; | 1548 | struct ieee80211_hw *hw = sc->hw; |
| 1548 | int error = 0; | 1549 | int error = 0, i; |
| 1549 | 1550 | ||
| 1550 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); | 1551 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); |
| 1551 | 1552 | ||
| @@ -1589,11 +1590,11 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1589 | /* initialize tx/rx engine */ | 1590 | /* initialize tx/rx engine */ |
| 1590 | error = ath_tx_init(sc, ATH_TXBUF); | 1591 | error = ath_tx_init(sc, ATH_TXBUF); |
| 1591 | if (error != 0) | 1592 | if (error != 0) |
| 1592 | goto detach; | 1593 | goto error_attach; |
| 1593 | 1594 | ||
| 1594 | error = ath_rx_init(sc, ATH_RXBUF); | 1595 | error = ath_rx_init(sc, ATH_RXBUF); |
| 1595 | if (error != 0) | 1596 | if (error != 0) |
| 1596 | goto detach; | 1597 | goto error_attach; |
| 1597 | 1598 | ||
| 1598 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 1599 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
| 1599 | /* Initialze h/w Rfkill */ | 1600 | /* Initialze h/w Rfkill */ |
| @@ -1601,8 +1602,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1601 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); | 1602 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); |
| 1602 | 1603 | ||
| 1603 | /* Initialize s/w rfkill */ | 1604 | /* Initialize s/w rfkill */ |
| 1604 | if (ath_init_sw_rfkill(sc)) | 1605 | error = ath_init_sw_rfkill(sc); |
| 1605 | goto detach; | 1606 | if (error) |
| 1607 | goto error_attach; | ||
| 1606 | #endif | 1608 | #endif |
| 1607 | 1609 | ||
| 1608 | error = ieee80211_register_hw(hw); | 1610 | error = ieee80211_register_hw(hw); |
| @@ -1611,8 +1613,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1611 | ath_init_leds(sc); | 1613 | ath_init_leds(sc); |
| 1612 | 1614 | ||
| 1613 | return 0; | 1615 | return 0; |
| 1614 | detach: | 1616 | |
| 1615 | ath_detach(sc); | 1617 | error_attach: |
| 1618 | /* cleanup tx queues */ | ||
| 1619 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
| 1620 | if (ATH_TXQ_SETUP(sc, i)) | ||
| 1621 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
| 1622 | |||
| 1623 | ath9k_hw_detach(sc->sc_ah); | ||
| 1624 | ath9k_exit_debug(sc); | ||
| 1625 | |||
| 1616 | return error; | 1626 | return error; |
| 1617 | } | 1627 | } |
| 1618 | 1628 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b0ee86c6268..ab13ff22a8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -148,7 +148,7 @@ static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
| 148 | pci_unmap_single(dev, | 148 | pci_unmap_single(dev, |
| 149 | pci_unmap_addr(&txq->cmd[index]->meta, mapping), | 149 | pci_unmap_addr(&txq->cmd[index]->meta, mapping), |
| 150 | pci_unmap_len(&txq->cmd[index]->meta, len), | 150 | pci_unmap_len(&txq->cmd[index]->meta, len), |
| 151 | PCI_DMA_TODEVICE); | 151 | PCI_DMA_BIDIRECTIONAL); |
| 152 | 152 | ||
| 153 | /* Unmap chunks, if any. */ | 153 | /* Unmap chunks, if any. */ |
| 154 | for (i = 1; i < num_tbs; i++) { | 154 | for (i = 1; i < num_tbs; i++) { |
| @@ -964,7 +964,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
| 964 | * within command buffer array. */ | 964 | * within command buffer array. */ |
| 965 | txcmd_phys = pci_map_single(priv->pci_dev, | 965 | txcmd_phys = pci_map_single(priv->pci_dev, |
| 966 | out_cmd, sizeof(struct iwl_cmd), | 966 | out_cmd, sizeof(struct iwl_cmd), |
| 967 | PCI_DMA_TODEVICE); | 967 | PCI_DMA_BIDIRECTIONAL); |
| 968 | pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys); | 968 | pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys); |
| 969 | pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd)); | 969 | pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd)); |
| 970 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 970 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
| @@ -1115,7 +1115,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1115 | IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); | 1115 | IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); |
| 1116 | 1116 | ||
| 1117 | phys_addr = pci_map_single(priv->pci_dev, out_cmd, | 1117 | phys_addr = pci_map_single(priv->pci_dev, out_cmd, |
| 1118 | len, PCI_DMA_TODEVICE); | 1118 | len, PCI_DMA_BIDIRECTIONAL); |
| 1119 | pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr); | 1119 | pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr); |
| 1120 | pci_unmap_len_set(&out_cmd->meta, len, len); | 1120 | pci_unmap_len_set(&out_cmd->meta, len, len); |
| 1121 | phys_addr += offsetof(struct iwl_cmd, hdr); | 1121 | phys_addr += offsetof(struct iwl_cmd, hdr); |
| @@ -1212,7 +1212,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, | |||
| 1212 | pci_unmap_single(priv->pci_dev, | 1212 | pci_unmap_single(priv->pci_dev, |
| 1213 | pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping), | 1213 | pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping), |
| 1214 | pci_unmap_len(&txq->cmd[cmd_idx]->meta, len), | 1214 | pci_unmap_len(&txq->cmd[cmd_idx]->meta, len), |
| 1215 | PCI_DMA_TODEVICE); | 1215 | PCI_DMA_BIDIRECTIONAL); |
| 1216 | 1216 | ||
| 1217 | for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; | 1217 | for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; |
| 1218 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1218 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 61d2f50470c..b118a35ec60 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
| @@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= { | |||
| 23 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, | 23 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, |
| 24 | struct ethtool_drvinfo *info) | 24 | struct ethtool_drvinfo *info) |
| 25 | { | 25 | { |
| 26 | struct lbs_private *priv = netdev_priv(dev); | 26 | struct lbs_private *priv = dev->ml_priv; |
| 27 | 27 | ||
| 28 | snprintf(info->fw_version, 32, "%u.%u.%u.p%u", | 28 | snprintf(info->fw_version, 32, "%u.%u.%u.p%u", |
| 29 | priv->fwrelease >> 24 & 0xff, | 29 | priv->fwrelease >> 24 & 0xff, |
| @@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev) | |||
| 47 | static int lbs_ethtool_get_eeprom(struct net_device *dev, | 47 | static int lbs_ethtool_get_eeprom(struct net_device *dev, |
| 48 | struct ethtool_eeprom *eeprom, u8 * bytes) | 48 | struct ethtool_eeprom *eeprom, u8 * bytes) |
| 49 | { | 49 | { |
| 50 | struct lbs_private *priv = netdev_priv(dev); | 50 | struct lbs_private *priv = dev->ml_priv; |
| 51 | struct cmd_ds_802_11_eeprom_access cmd; | 51 | struct cmd_ds_802_11_eeprom_access cmd; |
| 52 | int ret; | 52 | int ret; |
| 53 | 53 | ||
| @@ -76,7 +76,7 @@ out: | |||
| 76 | static void lbs_ethtool_get_stats(struct net_device *dev, | 76 | static void lbs_ethtool_get_stats(struct net_device *dev, |
| 77 | struct ethtool_stats *stats, uint64_t *data) | 77 | struct ethtool_stats *stats, uint64_t *data) |
| 78 | { | 78 | { |
| 79 | struct lbs_private *priv = netdev_priv(dev); | 79 | struct lbs_private *priv = dev->ml_priv; |
| 80 | struct cmd_ds_mesh_access mesh_access; | 80 | struct cmd_ds_mesh_access mesh_access; |
| 81 | int ret; | 81 | int ret; |
| 82 | 82 | ||
| @@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev, | |||
| 113 | 113 | ||
| 114 | static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) | 114 | static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) |
| 115 | { | 115 | { |
| 116 | struct lbs_private *priv = netdev_priv(dev); | 116 | struct lbs_private *priv = dev->ml_priv; |
| 117 | 117 | ||
| 118 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) | 118 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) |
| 119 | return MESH_STATS_NUM; | 119 | return MESH_STATS_NUM; |
| @@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev, | |||
| 143 | static void lbs_ethtool_get_wol(struct net_device *dev, | 143 | static void lbs_ethtool_get_wol(struct net_device *dev, |
| 144 | struct ethtool_wolinfo *wol) | 144 | struct ethtool_wolinfo *wol) |
| 145 | { | 145 | { |
| 146 | struct lbs_private *priv = netdev_priv(dev); | 146 | struct lbs_private *priv = dev->ml_priv; |
| 147 | 147 | ||
| 148 | if (priv->wol_criteria == 0xffffffff) { | 148 | if (priv->wol_criteria == 0xffffffff) { |
| 149 | /* Interface driver didn't configure wake */ | 149 | /* Interface driver didn't configure wake */ |
| @@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev, | |||
| 166 | static int lbs_ethtool_set_wol(struct net_device *dev, | 166 | static int lbs_ethtool_set_wol(struct net_device *dev, |
| 167 | struct ethtool_wolinfo *wol) | 167 | struct ethtool_wolinfo *wol) |
| 168 | { | 168 | { |
| 169 | struct lbs_private *priv = netdev_priv(dev); | 169 | struct lbs_private *priv = dev->ml_priv; |
| 170 | uint32_t criteria = 0; | 170 | uint32_t criteria = 0; |
| 171 | 171 | ||
| 172 | if (priv->wol_criteria == 0xffffffff && wol->wolopts) | 172 | if (priv->wol_criteria == 0xffffffff && wol->wolopts) |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 2fc637ad85c..ea3dc038be7 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
| @@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); | |||
| 59 | static ssize_t if_usb_firmware_set(struct device *dev, | 59 | static ssize_t if_usb_firmware_set(struct device *dev, |
| 60 | struct device_attribute *attr, const char *buf, size_t count) | 60 | struct device_attribute *attr, const char *buf, size_t count) |
| 61 | { | 61 | { |
| 62 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 62 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 63 | struct if_usb_card *cardp = priv->card; | 63 | struct if_usb_card *cardp = priv->card; |
| 64 | char fwname[FIRMWARE_NAME_MAX]; | 64 | char fwname[FIRMWARE_NAME_MAX]; |
| 65 | int ret; | 65 | int ret; |
| @@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); | |||
| 86 | static ssize_t if_usb_boot2_set(struct device *dev, | 86 | static ssize_t if_usb_boot2_set(struct device *dev, |
| 87 | struct device_attribute *attr, const char *buf, size_t count) | 87 | struct device_attribute *attr, const char *buf, size_t count) |
| 88 | { | 88 | { |
| 89 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 89 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 90 | struct if_usb_card *cardp = priv->card; | 90 | struct if_usb_card *cardp = priv->card; |
| 91 | char fwname[FIRMWARE_NAME_MAX]; | 91 | char fwname[FIRMWARE_NAME_MAX]; |
| 92 | int ret; | 92 | int ret; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4e0007d2003..f76623e0ff9 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
| @@ -222,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate) | |||
| 222 | static ssize_t lbs_anycast_get(struct device *dev, | 222 | static ssize_t lbs_anycast_get(struct device *dev, |
| 223 | struct device_attribute *attr, char * buf) | 223 | struct device_attribute *attr, char * buf) |
| 224 | { | 224 | { |
| 225 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 225 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 226 | struct cmd_ds_mesh_access mesh_access; | 226 | struct cmd_ds_mesh_access mesh_access; |
| 227 | int ret; | 227 | int ret; |
| 228 | 228 | ||
| @@ -241,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev, | |||
| 241 | static ssize_t lbs_anycast_set(struct device *dev, | 241 | static ssize_t lbs_anycast_set(struct device *dev, |
| 242 | struct device_attribute *attr, const char * buf, size_t count) | 242 | struct device_attribute *attr, const char * buf, size_t count) |
| 243 | { | 243 | { |
| 244 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 244 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 245 | struct cmd_ds_mesh_access mesh_access; | 245 | struct cmd_ds_mesh_access mesh_access; |
| 246 | uint32_t datum; | 246 | uint32_t datum; |
| 247 | int ret; | 247 | int ret; |
| @@ -263,7 +263,7 @@ static ssize_t lbs_anycast_set(struct device *dev, | |||
| 263 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | 263 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, |
| 264 | struct device_attribute *attr, char *buf) | 264 | struct device_attribute *attr, char *buf) |
| 265 | { | 265 | { |
| 266 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 266 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 267 | struct cmd_ds_mesh_access mesh_access; | 267 | struct cmd_ds_mesh_access mesh_access; |
| 268 | int ret; | 268 | int ret; |
| 269 | u32 retry_limit; | 269 | u32 retry_limit; |
| @@ -286,7 +286,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | |||
| 286 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, | 286 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, |
| 287 | struct device_attribute *attr, const char *buf, size_t count) | 287 | struct device_attribute *attr, const char *buf, size_t count) |
| 288 | { | 288 | { |
| 289 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 289 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 290 | struct cmd_ds_mesh_access mesh_access; | 290 | struct cmd_ds_mesh_access mesh_access; |
| 291 | int ret; | 291 | int ret; |
| 292 | unsigned long retry_limit; | 292 | unsigned long retry_limit; |
| @@ -321,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv); | |||
| 321 | static ssize_t lbs_rtap_get(struct device *dev, | 321 | static ssize_t lbs_rtap_get(struct device *dev, |
| 322 | struct device_attribute *attr, char * buf) | 322 | struct device_attribute *attr, char * buf) |
| 323 | { | 323 | { |
| 324 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 324 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 325 | return snprintf(buf, 5, "0x%X\n", priv->monitormode); | 325 | return snprintf(buf, 5, "0x%X\n", priv->monitormode); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| @@ -332,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
| 332 | struct device_attribute *attr, const char * buf, size_t count) | 332 | struct device_attribute *attr, const char * buf, size_t count) |
| 333 | { | 333 | { |
| 334 | int monitor_mode; | 334 | int monitor_mode; |
| 335 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 335 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 336 | 336 | ||
| 337 | sscanf(buf, "%x", &monitor_mode); | 337 | sscanf(buf, "%x", &monitor_mode); |
| 338 | if (monitor_mode) { | 338 | if (monitor_mode) { |
| @@ -383,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); | |||
| 383 | static ssize_t lbs_mesh_get(struct device *dev, | 383 | static ssize_t lbs_mesh_get(struct device *dev, |
| 384 | struct device_attribute *attr, char * buf) | 384 | struct device_attribute *attr, char * buf) |
| 385 | { | 385 | { |
| 386 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 386 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 387 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); | 387 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| @@ -393,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev, | |||
| 393 | static ssize_t lbs_mesh_set(struct device *dev, | 393 | static ssize_t lbs_mesh_set(struct device *dev, |
| 394 | struct device_attribute *attr, const char * buf, size_t count) | 394 | struct device_attribute *attr, const char * buf, size_t count) |
| 395 | { | 395 | { |
| 396 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 396 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 397 | int enable; | 397 | int enable; |
| 398 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; | 398 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; |
| 399 | 399 | ||
| @@ -452,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = { | |||
| 452 | */ | 452 | */ |
| 453 | static int lbs_dev_open(struct net_device *dev) | 453 | static int lbs_dev_open(struct net_device *dev) |
| 454 | { | 454 | { |
| 455 | struct lbs_private *priv = netdev_priv(dev) ; | 455 | struct lbs_private *priv = dev->ml_priv; |
| 456 | int ret = 0; | 456 | int ret = 0; |
| 457 | 457 | ||
| 458 | lbs_deb_enter(LBS_DEB_NET); | 458 | lbs_deb_enter(LBS_DEB_NET); |
| @@ -521,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev) | |||
| 521 | */ | 521 | */ |
| 522 | static int lbs_eth_stop(struct net_device *dev) | 522 | static int lbs_eth_stop(struct net_device *dev) |
| 523 | { | 523 | { |
| 524 | struct lbs_private *priv = netdev_priv(dev); | 524 | struct lbs_private *priv = dev->ml_priv; |
| 525 | 525 | ||
| 526 | lbs_deb_enter(LBS_DEB_NET); | 526 | lbs_deb_enter(LBS_DEB_NET); |
| 527 | 527 | ||
| @@ -538,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev) | |||
| 538 | 538 | ||
| 539 | static void lbs_tx_timeout(struct net_device *dev) | 539 | static void lbs_tx_timeout(struct net_device *dev) |
| 540 | { | 540 | { |
| 541 | struct lbs_private *priv = netdev_priv(dev); | 541 | struct lbs_private *priv = dev->ml_priv; |
| 542 | 542 | ||
| 543 | lbs_deb_enter(LBS_DEB_TX); | 543 | lbs_deb_enter(LBS_DEB_TX); |
| 544 | 544 | ||
| @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done); | |||
| 590 | */ | 590 | */ |
| 591 | static struct net_device_stats *lbs_get_stats(struct net_device *dev) | 591 | static struct net_device_stats *lbs_get_stats(struct net_device *dev) |
| 592 | { | 592 | { |
| 593 | struct lbs_private *priv = netdev_priv(dev); | 593 | struct lbs_private *priv = dev->ml_priv; |
| 594 | 594 | ||
| 595 | lbs_deb_enter(LBS_DEB_NET); | 595 | lbs_deb_enter(LBS_DEB_NET); |
| 596 | return &priv->stats; | 596 | return &priv->stats; |
| @@ -599,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev) | |||
| 599 | static int lbs_set_mac_address(struct net_device *dev, void *addr) | 599 | static int lbs_set_mac_address(struct net_device *dev, void *addr) |
| 600 | { | 600 | { |
| 601 | int ret = 0; | 601 | int ret = 0; |
| 602 | struct lbs_private *priv = netdev_priv(dev); | 602 | struct lbs_private *priv = dev->ml_priv; |
| 603 | struct sockaddr *phwaddr = addr; | 603 | struct sockaddr *phwaddr = addr; |
| 604 | struct cmd_ds_802_11_mac_address cmd; | 604 | struct cmd_ds_802_11_mac_address cmd; |
| 605 | 605 | ||
| @@ -732,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work) | |||
| 732 | 732 | ||
| 733 | static void lbs_set_multicast_list(struct net_device *dev) | 733 | static void lbs_set_multicast_list(struct net_device *dev) |
| 734 | { | 734 | { |
| 735 | struct lbs_private *priv = netdev_priv(dev); | 735 | struct lbs_private *priv = dev->ml_priv; |
| 736 | 736 | ||
| 737 | schedule_work(&priv->mcast_work); | 737 | schedule_work(&priv->mcast_work); |
| 738 | } | 738 | } |
| @@ -748,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev) | |||
| 748 | static int lbs_thread(void *data) | 748 | static int lbs_thread(void *data) |
| 749 | { | 749 | { |
| 750 | struct net_device *dev = data; | 750 | struct net_device *dev = data; |
| 751 | struct lbs_private *priv = netdev_priv(dev); | 751 | struct lbs_private *priv = dev->ml_priv; |
| 752 | wait_queue_t wait; | 752 | wait_queue_t wait; |
| 753 | 753 | ||
| 754 | lbs_deb_enter(LBS_DEB_THREAD); | 754 | lbs_deb_enter(LBS_DEB_THREAD); |
| @@ -1184,6 +1184,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
| 1184 | goto done; | 1184 | goto done; |
| 1185 | } | 1185 | } |
| 1186 | priv = netdev_priv(dev); | 1186 | priv = netdev_priv(dev); |
| 1187 | dev->ml_priv = priv; | ||
| 1187 | 1188 | ||
| 1188 | if (lbs_init_adapter(priv)) { | 1189 | if (lbs_init_adapter(priv)) { |
| 1189 | lbs_pr_err("failed to initialize adapter structure.\n"); | 1190 | lbs_pr_err("failed to initialize adapter structure.\n"); |
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c index d42b7a5a1b3..18fe29faf99 100644 --- a/drivers/net/wireless/libertas/persistcfg.c +++ b/drivers/net/wireless/libertas/persistcfg.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | static int mesh_get_default_parameters(struct device *dev, | 18 | static int mesh_get_default_parameters(struct device *dev, |
| 19 | struct mrvl_mesh_defaults *defs) | 19 | struct mrvl_mesh_defaults *defs) |
| 20 | { | 20 | { |
| 21 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 21 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 22 | struct cmd_ds_mesh_config cmd; | 22 | struct cmd_ds_mesh_config cmd; |
| 23 | int ret; | 23 | int ret; |
| 24 | 24 | ||
| @@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev, | |||
| 57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, | 57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, |
| 58 | const char *buf, size_t count) | 58 | const char *buf, size_t count) |
| 59 | { | 59 | { |
| 60 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 60 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 61 | struct cmd_ds_mesh_config cmd; | 61 | struct cmd_ds_mesh_config cmd; |
| 62 | uint32_t datum; | 62 | uint32_t datum; |
| 63 | int ret; | 63 | int ret; |
| @@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev, | |||
| 100 | static ssize_t boottime_set(struct device *dev, | 100 | static ssize_t boottime_set(struct device *dev, |
| 101 | struct device_attribute *attr, const char *buf, size_t count) | 101 | struct device_attribute *attr, const char *buf, size_t count) |
| 102 | { | 102 | { |
| 103 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 103 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 104 | struct cmd_ds_mesh_config cmd; | 104 | struct cmd_ds_mesh_config cmd; |
| 105 | uint32_t datum; | 105 | uint32_t datum; |
| 106 | int ret; | 106 | int ret; |
| @@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev, | |||
| 152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, | 152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, |
| 153 | const char *buf, size_t count) | 153 | const char *buf, size_t count) |
| 154 | { | 154 | { |
| 155 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 155 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 156 | struct cmd_ds_mesh_config cmd; | 156 | struct cmd_ds_mesh_config cmd; |
| 157 | uint32_t datum; | 157 | uint32_t datum; |
| 158 | int ret; | 158 | int ret; |
| @@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | |||
| 210 | struct cmd_ds_mesh_config cmd; | 210 | struct cmd_ds_mesh_config cmd; |
| 211 | struct mrvl_mesh_defaults defs; | 211 | struct mrvl_mesh_defaults defs; |
| 212 | struct mrvl_meshie *ie; | 212 | struct mrvl_meshie *ie; |
| 213 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 213 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 214 | int len; | 214 | int len; |
| 215 | int ret; | 215 | int ret; |
| 216 | 216 | ||
| @@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev, | |||
| 269 | struct cmd_ds_mesh_config cmd; | 269 | struct cmd_ds_mesh_config cmd; |
| 270 | struct mrvl_mesh_defaults defs; | 270 | struct mrvl_mesh_defaults defs; |
| 271 | struct mrvl_meshie *ie; | 271 | struct mrvl_meshie *ie; |
| 272 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 272 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 273 | uint32_t datum; | 273 | uint32_t datum; |
| 274 | int ret; | 274 | int ret; |
| 275 | 275 | ||
| @@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, | |||
| 323 | struct cmd_ds_mesh_config cmd; | 323 | struct cmd_ds_mesh_config cmd; |
| 324 | struct mrvl_mesh_defaults defs; | 324 | struct mrvl_mesh_defaults defs; |
| 325 | struct mrvl_meshie *ie; | 325 | struct mrvl_meshie *ie; |
| 326 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 326 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 327 | uint32_t datum; | 327 | uint32_t datum; |
| 328 | int ret; | 328 | int ret; |
| 329 | 329 | ||
| @@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, | |||
| 377 | struct cmd_ds_mesh_config cmd; | 377 | struct cmd_ds_mesh_config cmd; |
| 378 | struct mrvl_mesh_defaults defs; | 378 | struct mrvl_mesh_defaults defs; |
| 379 | struct mrvl_meshie *ie; | 379 | struct mrvl_meshie *ie; |
| 380 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 380 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 381 | uint32_t datum; | 381 | uint32_t datum; |
| 382 | int ret; | 382 | int ret; |
| 383 | 383 | ||
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 57f6c12cda2..9014950f432 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
| @@ -945,7 +945,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
| 945 | union iwreq_data *wrqu, char *extra) | 945 | union iwreq_data *wrqu, char *extra) |
| 946 | { | 946 | { |
| 947 | DECLARE_SSID_BUF(ssid); | 947 | DECLARE_SSID_BUF(ssid); |
| 948 | struct lbs_private *priv = netdev_priv(dev); | 948 | struct lbs_private *priv = dev->ml_priv; |
| 949 | int ret = 0; | 949 | int ret = 0; |
| 950 | 950 | ||
| 951 | lbs_deb_enter(LBS_DEB_WEXT); | 951 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1008,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
| 1008 | struct iw_point *dwrq, char *extra) | 1008 | struct iw_point *dwrq, char *extra) |
| 1009 | { | 1009 | { |
| 1010 | #define SCAN_ITEM_SIZE 128 | 1010 | #define SCAN_ITEM_SIZE 128 |
| 1011 | struct lbs_private *priv = netdev_priv(dev); | 1011 | struct lbs_private *priv = dev->ml_priv; |
| 1012 | int err = 0; | 1012 | int err = 0; |
| 1013 | char *ev = extra; | 1013 | char *ev = extra; |
| 1014 | char *stop = ev + dwrq->length; | 1014 | char *stop = ev + dwrq->length; |
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index dac46264117..68bec31ae03 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
| @@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) | |||
| 60 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 60 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
| 61 | { | 61 | { |
| 62 | unsigned long flags; | 62 | unsigned long flags; |
| 63 | struct lbs_private *priv = netdev_priv(dev); | 63 | struct lbs_private *priv = dev->ml_priv; |
| 64 | struct txpd *txpd; | 64 | struct txpd *txpd; |
| 65 | char *p802x_hdr; | 65 | char *p802x_hdr; |
| 66 | uint16_t pkt_len; | 66 | uint16_t pkt_len; |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6102e08179..f16d136ab4b 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
| @@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, | |||
| 163 | static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | 163 | static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, |
| 164 | struct iw_freq *fwrq, char *extra) | 164 | struct iw_freq *fwrq, char *extra) |
| 165 | { | 165 | { |
| 166 | struct lbs_private *priv = netdev_priv(dev); | 166 | struct lbs_private *priv = dev->ml_priv; |
| 167 | struct chan_freq_power *cfp; | 167 | struct chan_freq_power *cfp; |
| 168 | 168 | ||
| 169 | lbs_deb_enter(LBS_DEB_WEXT); | 169 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | |||
| 189 | static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, | 189 | static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, |
| 190 | struct sockaddr *awrq, char *extra) | 190 | struct sockaddr *awrq, char *extra) |
| 191 | { | 191 | { |
| 192 | struct lbs_private *priv = netdev_priv(dev); | 192 | struct lbs_private *priv = dev->ml_priv; |
| 193 | 193 | ||
| 194 | lbs_deb_enter(LBS_DEB_WEXT); | 194 | lbs_deb_enter(LBS_DEB_WEXT); |
| 195 | 195 | ||
| @@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, | |||
| 207 | static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, | 207 | static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, |
| 208 | struct iw_point *dwrq, char *extra) | 208 | struct iw_point *dwrq, char *extra) |
| 209 | { | 209 | { |
| 210 | struct lbs_private *priv = netdev_priv(dev); | 210 | struct lbs_private *priv = dev->ml_priv; |
| 211 | 211 | ||
| 212 | lbs_deb_enter(LBS_DEB_WEXT); | 212 | lbs_deb_enter(LBS_DEB_WEXT); |
| 213 | 213 | ||
| @@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, | |||
| 231 | static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | 231 | static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, |
| 232 | struct iw_point *dwrq, char *extra) | 232 | struct iw_point *dwrq, char *extra) |
| 233 | { | 233 | { |
| 234 | struct lbs_private *priv = netdev_priv(dev); | 234 | struct lbs_private *priv = dev->ml_priv; |
| 235 | 235 | ||
| 236 | lbs_deb_enter(LBS_DEB_WEXT); | 236 | lbs_deb_enter(LBS_DEB_WEXT); |
| 237 | 237 | ||
| @@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
| 248 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | 248 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, |
| 249 | struct iw_point *dwrq, char *extra) | 249 | struct iw_point *dwrq, char *extra) |
| 250 | { | 250 | { |
| 251 | struct lbs_private *priv = netdev_priv(dev); | 251 | struct lbs_private *priv = dev->ml_priv; |
| 252 | 252 | ||
| 253 | lbs_deb_enter(LBS_DEB_WEXT); | 253 | lbs_deb_enter(LBS_DEB_WEXT); |
| 254 | 254 | ||
| @@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | |||
| 273 | struct iw_param *vwrq, char *extra) | 273 | struct iw_param *vwrq, char *extra) |
| 274 | { | 274 | { |
| 275 | int ret = 0; | 275 | int ret = 0; |
| 276 | struct lbs_private *priv = netdev_priv(dev); | 276 | struct lbs_private *priv = dev->ml_priv; |
| 277 | u32 val = vwrq->value; | 277 | u32 val = vwrq->value; |
| 278 | 278 | ||
| 279 | lbs_deb_enter(LBS_DEB_WEXT); | 279 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | |||
| 293 | static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, | 293 | static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, |
| 294 | struct iw_param *vwrq, char *extra) | 294 | struct iw_param *vwrq, char *extra) |
| 295 | { | 295 | { |
| 296 | struct lbs_private *priv = netdev_priv(dev); | 296 | struct lbs_private *priv = dev->ml_priv; |
| 297 | int ret = 0; | 297 | int ret = 0; |
| 298 | u16 val = 0; | 298 | u16 val = 0; |
| 299 | 299 | ||
| @@ -315,7 +315,7 @@ out: | |||
| 315 | static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, | 315 | static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, |
| 316 | struct iw_param *vwrq, char *extra) | 316 | struct iw_param *vwrq, char *extra) |
| 317 | { | 317 | { |
| 318 | struct lbs_private *priv = netdev_priv(dev); | 318 | struct lbs_private *priv = dev->ml_priv; |
| 319 | int ret = 0; | 319 | int ret = 0; |
| 320 | u32 val = vwrq->value; | 320 | u32 val = vwrq->value; |
| 321 | 321 | ||
| @@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, | |||
| 336 | static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, | 336 | static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, |
| 337 | struct iw_param *vwrq, char *extra) | 337 | struct iw_param *vwrq, char *extra) |
| 338 | { | 338 | { |
| 339 | struct lbs_private *priv = netdev_priv(dev); | 339 | struct lbs_private *priv = dev->ml_priv; |
| 340 | int ret = 0; | 340 | int ret = 0; |
| 341 | u16 val = 0; | 341 | u16 val = 0; |
| 342 | 342 | ||
| @@ -359,7 +359,7 @@ out: | |||
| 359 | static int lbs_get_mode(struct net_device *dev, | 359 | static int lbs_get_mode(struct net_device *dev, |
| 360 | struct iw_request_info *info, u32 * uwrq, char *extra) | 360 | struct iw_request_info *info, u32 * uwrq, char *extra) |
| 361 | { | 361 | { |
| 362 | struct lbs_private *priv = netdev_priv(dev); | 362 | struct lbs_private *priv = dev->ml_priv; |
| 363 | 363 | ||
| 364 | lbs_deb_enter(LBS_DEB_WEXT); | 364 | lbs_deb_enter(LBS_DEB_WEXT); |
| 365 | 365 | ||
| @@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev, | |||
| 385 | struct iw_request_info *info, | 385 | struct iw_request_info *info, |
| 386 | struct iw_param *vwrq, char *extra) | 386 | struct iw_param *vwrq, char *extra) |
| 387 | { | 387 | { |
| 388 | struct lbs_private *priv = netdev_priv(dev); | 388 | struct lbs_private *priv = dev->ml_priv; |
| 389 | s16 curlevel = 0; | 389 | s16 curlevel = 0; |
| 390 | int ret = 0; | 390 | int ret = 0; |
| 391 | 391 | ||
| @@ -418,7 +418,7 @@ out: | |||
| 418 | static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, | 418 | static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, |
| 419 | struct iw_param *vwrq, char *extra) | 419 | struct iw_param *vwrq, char *extra) |
| 420 | { | 420 | { |
| 421 | struct lbs_private *priv = netdev_priv(dev); | 421 | struct lbs_private *priv = dev->ml_priv; |
| 422 | int ret = 0; | 422 | int ret = 0; |
| 423 | u16 slimit = 0, llimit = 0; | 423 | u16 slimit = 0, llimit = 0; |
| 424 | 424 | ||
| @@ -466,7 +466,7 @@ out: | |||
| 466 | static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, | 466 | static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, |
| 467 | struct iw_param *vwrq, char *extra) | 467 | struct iw_param *vwrq, char *extra) |
| 468 | { | 468 | { |
| 469 | struct lbs_private *priv = netdev_priv(dev); | 469 | struct lbs_private *priv = dev->ml_priv; |
| 470 | int ret = 0; | 470 | int ret = 0; |
| 471 | u16 val = 0; | 471 | u16 val = 0; |
| 472 | 472 | ||
| @@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
| 542 | struct iw_point *dwrq, char *extra) | 542 | struct iw_point *dwrq, char *extra) |
| 543 | { | 543 | { |
| 544 | int i, j; | 544 | int i, j; |
| 545 | struct lbs_private *priv = netdev_priv(dev); | 545 | struct lbs_private *priv = dev->ml_priv; |
| 546 | struct iw_range *range = (struct iw_range *)extra; | 546 | struct iw_range *range = (struct iw_range *)extra; |
| 547 | struct chan_freq_power *cfp; | 547 | struct chan_freq_power *cfp; |
| 548 | u8 rates[MAX_RATES + 1]; | 548 | u8 rates[MAX_RATES + 1]; |
| @@ -708,7 +708,7 @@ out: | |||
| 708 | static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | 708 | static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, |
| 709 | struct iw_param *vwrq, char *extra) | 709 | struct iw_param *vwrq, char *extra) |
| 710 | { | 710 | { |
| 711 | struct lbs_private *priv = netdev_priv(dev); | 711 | struct lbs_private *priv = dev->ml_priv; |
| 712 | 712 | ||
| 713 | lbs_deb_enter(LBS_DEB_WEXT); | 713 | lbs_deb_enter(LBS_DEB_WEXT); |
| 714 | 714 | ||
| @@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
| 758 | static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, | 758 | static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, |
| 759 | struct iw_param *vwrq, char *extra) | 759 | struct iw_param *vwrq, char *extra) |
| 760 | { | 760 | { |
| 761 | struct lbs_private *priv = netdev_priv(dev); | 761 | struct lbs_private *priv = dev->ml_priv; |
| 762 | 762 | ||
| 763 | lbs_deb_enter(LBS_DEB_WEXT); | 763 | lbs_deb_enter(LBS_DEB_WEXT); |
| 764 | 764 | ||
| @@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
| 781 | EXCELLENT = 95, | 781 | EXCELLENT = 95, |
| 782 | PERFECT = 100 | 782 | PERFECT = 100 |
| 783 | }; | 783 | }; |
| 784 | struct lbs_private *priv = netdev_priv(dev); | 784 | struct lbs_private *priv = dev->ml_priv; |
| 785 | u32 rssi_qual; | 785 | u32 rssi_qual; |
| 786 | u32 tx_qual; | 786 | u32 tx_qual; |
| 787 | u32 quality = 0; | 787 | u32 quality = 0; |
| @@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, | |||
| 886 | struct iw_freq *fwrq, char *extra) | 886 | struct iw_freq *fwrq, char *extra) |
| 887 | { | 887 | { |
| 888 | int ret = -EINVAL; | 888 | int ret = -EINVAL; |
| 889 | struct lbs_private *priv = netdev_priv(dev); | 889 | struct lbs_private *priv = dev->ml_priv; |
| 890 | struct chan_freq_power *cfp; | 890 | struct chan_freq_power *cfp; |
| 891 | struct assoc_request * assoc_req; | 891 | struct assoc_request * assoc_req; |
| 892 | 892 | ||
| @@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
| 943 | struct iw_request_info *info, | 943 | struct iw_request_info *info, |
| 944 | struct iw_freq *fwrq, char *extra) | 944 | struct iw_freq *fwrq, char *extra) |
| 945 | { | 945 | { |
| 946 | struct lbs_private *priv = netdev_priv(dev); | 946 | struct lbs_private *priv = dev->ml_priv; |
| 947 | struct chan_freq_power *cfp; | 947 | struct chan_freq_power *cfp; |
| 948 | int ret = -EINVAL; | 948 | int ret = -EINVAL; |
| 949 | 949 | ||
| @@ -994,7 +994,7 @@ out: | |||
| 994 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | 994 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, |
| 995 | struct iw_param *vwrq, char *extra) | 995 | struct iw_param *vwrq, char *extra) |
| 996 | { | 996 | { |
| 997 | struct lbs_private *priv = netdev_priv(dev); | 997 | struct lbs_private *priv = dev->ml_priv; |
| 998 | u8 new_rate = 0; | 998 | u8 new_rate = 0; |
| 999 | int ret = -EINVAL; | 999 | int ret = -EINVAL; |
| 1000 | u8 rates[MAX_RATES + 1]; | 1000 | u8 rates[MAX_RATES + 1]; |
| @@ -1054,7 +1054,7 @@ out: | |||
| 1054 | static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, | 1054 | static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, |
| 1055 | struct iw_param *vwrq, char *extra) | 1055 | struct iw_param *vwrq, char *extra) |
| 1056 | { | 1056 | { |
| 1057 | struct lbs_private *priv = netdev_priv(dev); | 1057 | struct lbs_private *priv = dev->ml_priv; |
| 1058 | 1058 | ||
| 1059 | lbs_deb_enter(LBS_DEB_WEXT); | 1059 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1060 | 1060 | ||
| @@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev, | |||
| 1079 | struct iw_request_info *info, u32 * uwrq, char *extra) | 1079 | struct iw_request_info *info, u32 * uwrq, char *extra) |
| 1080 | { | 1080 | { |
| 1081 | int ret = 0; | 1081 | int ret = 0; |
| 1082 | struct lbs_private *priv = netdev_priv(dev); | 1082 | struct lbs_private *priv = dev->ml_priv; |
| 1083 | struct assoc_request * assoc_req; | 1083 | struct assoc_request * assoc_req; |
| 1084 | 1084 | ||
| 1085 | lbs_deb_enter(LBS_DEB_WEXT); | 1085 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev, | |||
| 1124 | struct iw_request_info *info, | 1124 | struct iw_request_info *info, |
| 1125 | struct iw_point *dwrq, u8 * extra) | 1125 | struct iw_point *dwrq, u8 * extra) |
| 1126 | { | 1126 | { |
| 1127 | struct lbs_private *priv = netdev_priv(dev); | 1127 | struct lbs_private *priv = dev->ml_priv; |
| 1128 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 1128 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
| 1129 | 1129 | ||
| 1130 | lbs_deb_enter(LBS_DEB_WEXT); | 1130 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev, | |||
| 1319 | struct iw_point *dwrq, char *extra) | 1319 | struct iw_point *dwrq, char *extra) |
| 1320 | { | 1320 | { |
| 1321 | int ret = 0; | 1321 | int ret = 0; |
| 1322 | struct lbs_private *priv = netdev_priv(dev); | 1322 | struct lbs_private *priv = dev->ml_priv; |
| 1323 | struct assoc_request * assoc_req; | 1323 | struct assoc_request * assoc_req; |
| 1324 | u16 is_default = 0, index = 0, set_tx_key = 0; | 1324 | u16 is_default = 0, index = 0, set_tx_key = 0; |
| 1325 | 1325 | ||
| @@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev, | |||
| 1395 | char *extra) | 1395 | char *extra) |
| 1396 | { | 1396 | { |
| 1397 | int ret = -EINVAL; | 1397 | int ret = -EINVAL; |
| 1398 | struct lbs_private *priv = netdev_priv(dev); | 1398 | struct lbs_private *priv = dev->ml_priv; |
| 1399 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1399 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1400 | int index, max_key_len; | 1400 | int index, max_key_len; |
| 1401 | 1401 | ||
| @@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev, | |||
| 1501 | char *extra) | 1501 | char *extra) |
| 1502 | { | 1502 | { |
| 1503 | int ret = 0; | 1503 | int ret = 0; |
| 1504 | struct lbs_private *priv = netdev_priv(dev); | 1504 | struct lbs_private *priv = dev->ml_priv; |
| 1505 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1505 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1506 | int alg = ext->alg; | 1506 | int alg = ext->alg; |
| 1507 | struct assoc_request * assoc_req; | 1507 | struct assoc_request * assoc_req; |
| @@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev, | |||
| 1639 | struct iw_point *dwrq, | 1639 | struct iw_point *dwrq, |
| 1640 | char *extra) | 1640 | char *extra) |
| 1641 | { | 1641 | { |
| 1642 | struct lbs_private *priv = netdev_priv(dev); | 1642 | struct lbs_private *priv = dev->ml_priv; |
| 1643 | int ret = 0; | 1643 | int ret = 0; |
| 1644 | struct assoc_request * assoc_req; | 1644 | struct assoc_request * assoc_req; |
| 1645 | 1645 | ||
| @@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev, | |||
| 1685 | char *extra) | 1685 | char *extra) |
| 1686 | { | 1686 | { |
| 1687 | int ret = 0; | 1687 | int ret = 0; |
| 1688 | struct lbs_private *priv = netdev_priv(dev); | 1688 | struct lbs_private *priv = dev->ml_priv; |
| 1689 | 1689 | ||
| 1690 | lbs_deb_enter(LBS_DEB_WEXT); | 1690 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1691 | 1691 | ||
| @@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev, | |||
| 1713 | struct iw_param *dwrq, | 1713 | struct iw_param *dwrq, |
| 1714 | char *extra) | 1714 | char *extra) |
| 1715 | { | 1715 | { |
| 1716 | struct lbs_private *priv = netdev_priv(dev); | 1716 | struct lbs_private *priv = dev->ml_priv; |
| 1717 | struct assoc_request * assoc_req; | 1717 | struct assoc_request * assoc_req; |
| 1718 | int ret = 0; | 1718 | int ret = 0; |
| 1719 | int updated = 0; | 1719 | int updated = 0; |
| @@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev, | |||
| 1816 | char *extra) | 1816 | char *extra) |
| 1817 | { | 1817 | { |
| 1818 | int ret = 0; | 1818 | int ret = 0; |
| 1819 | struct lbs_private *priv = netdev_priv(dev); | 1819 | struct lbs_private *priv = dev->ml_priv; |
| 1820 | 1820 | ||
| 1821 | lbs_deb_enter(LBS_DEB_WEXT); | 1821 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1822 | 1822 | ||
| @@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, | |||
| 1857 | struct iw_param *vwrq, char *extra) | 1857 | struct iw_param *vwrq, char *extra) |
| 1858 | { | 1858 | { |
| 1859 | int ret = 0; | 1859 | int ret = 0; |
| 1860 | struct lbs_private *priv = netdev_priv(dev); | 1860 | struct lbs_private *priv = dev->ml_priv; |
| 1861 | s16 dbm = (s16) vwrq->value; | 1861 | s16 dbm = (s16) vwrq->value; |
| 1862 | 1862 | ||
| 1863 | lbs_deb_enter(LBS_DEB_WEXT); | 1863 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1936,7 +1936,7 @@ out: | |||
| 1936 | static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | 1936 | static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, |
| 1937 | struct iw_point *dwrq, char *extra) | 1937 | struct iw_point *dwrq, char *extra) |
| 1938 | { | 1938 | { |
| 1939 | struct lbs_private *priv = netdev_priv(dev); | 1939 | struct lbs_private *priv = dev->ml_priv; |
| 1940 | 1940 | ||
| 1941 | lbs_deb_enter(LBS_DEB_WEXT); | 1941 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1942 | 1942 | ||
| @@ -1971,7 +1971,7 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | |||
| 1971 | static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | 1971 | static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, |
| 1972 | struct iw_point *dwrq, char *extra) | 1972 | struct iw_point *dwrq, char *extra) |
| 1973 | { | 1973 | { |
| 1974 | struct lbs_private *priv = netdev_priv(dev); | 1974 | struct lbs_private *priv = dev->ml_priv; |
| 1975 | int ret = 0; | 1975 | int ret = 0; |
| 1976 | u8 ssid[IW_ESSID_MAX_SIZE]; | 1976 | u8 ssid[IW_ESSID_MAX_SIZE]; |
| 1977 | u8 ssid_len = 0; | 1977 | u8 ssid_len = 0; |
| @@ -2040,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev, | |||
| 2040 | struct iw_request_info *info, | 2040 | struct iw_request_info *info, |
| 2041 | struct iw_point *dwrq, char *extra) | 2041 | struct iw_point *dwrq, char *extra) |
| 2042 | { | 2042 | { |
| 2043 | struct lbs_private *priv = netdev_priv(dev); | 2043 | struct lbs_private *priv = dev->ml_priv; |
| 2044 | 2044 | ||
| 2045 | lbs_deb_enter(LBS_DEB_WEXT); | 2045 | lbs_deb_enter(LBS_DEB_WEXT); |
| 2046 | 2046 | ||
| @@ -2058,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
| 2058 | struct iw_request_info *info, | 2058 | struct iw_request_info *info, |
| 2059 | struct iw_point *dwrq, char *extra) | 2059 | struct iw_point *dwrq, char *extra) |
| 2060 | { | 2060 | { |
| 2061 | struct lbs_private *priv = netdev_priv(dev); | 2061 | struct lbs_private *priv = dev->ml_priv; |
| 2062 | int ret = 0; | 2062 | int ret = 0; |
| 2063 | 2063 | ||
| 2064 | lbs_deb_enter(LBS_DEB_WEXT); | 2064 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -2102,7 +2102,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
| 2102 | static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, | 2102 | static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, |
| 2103 | struct sockaddr *awrq, char *extra) | 2103 | struct sockaddr *awrq, char *extra) |
| 2104 | { | 2104 | { |
| 2105 | struct lbs_private *priv = netdev_priv(dev); | 2105 | struct lbs_private *priv = dev->ml_priv; |
| 2106 | struct assoc_request * assoc_req; | 2106 | struct assoc_request * assoc_req; |
| 2107 | int ret = 0; | 2107 | int ret = 0; |
| 2108 | 2108 | ||
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 45a04faa781..067d1a9c728 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c | |||
| @@ -3157,8 +3157,20 @@ static int orinoco_pm_notifier(struct notifier_block *notifier, | |||
| 3157 | 3157 | ||
| 3158 | return NOTIFY_DONE; | 3158 | return NOTIFY_DONE; |
| 3159 | } | 3159 | } |
| 3160 | |||
| 3161 | static void orinoco_register_pm_notifier(struct orinoco_private *priv) | ||
| 3162 | { | ||
| 3163 | priv->pm_notifier.notifier_call = orinoco_pm_notifier; | ||
| 3164 | register_pm_notifier(&priv->pm_notifier); | ||
| 3165 | } | ||
| 3166 | |||
| 3167 | static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) | ||
| 3168 | { | ||
| 3169 | unregister_pm_notifier(&priv->pm_notifier); | ||
| 3170 | } | ||
| 3160 | #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ | 3171 | #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ |
| 3161 | #define orinoco_pm_notifier NULL | 3172 | #define orinoco_register_pm_notifier(priv) do { } while(0) |
| 3173 | #define orinoco_unregister_pm_notifier(priv) do { } while(0) | ||
| 3162 | #endif | 3174 | #endif |
| 3163 | 3175 | ||
| 3164 | /********************************************************************/ | 3176 | /********************************************************************/ |
| @@ -3648,8 +3660,7 @@ struct net_device | |||
| 3648 | priv->cached_fw = NULL; | 3660 | priv->cached_fw = NULL; |
| 3649 | 3661 | ||
| 3650 | /* Register PM notifiers */ | 3662 | /* Register PM notifiers */ |
| 3651 | priv->pm_notifier.notifier_call = orinoco_pm_notifier; | 3663 | orinoco_register_pm_notifier(priv); |
| 3652 | register_pm_notifier(&priv->pm_notifier); | ||
| 3653 | 3664 | ||
| 3654 | return dev; | 3665 | return dev; |
| 3655 | } | 3666 | } |
| @@ -3673,7 +3684,7 @@ void free_orinocodev(struct net_device *dev) | |||
| 3673 | kfree(rx_data); | 3684 | kfree(rx_data); |
| 3674 | } | 3685 | } |
| 3675 | 3686 | ||
| 3676 | unregister_pm_notifier(&priv->pm_notifier); | 3687 | orinoco_unregister_pm_notifier(priv); |
| 3677 | orinoco_uncache_fw(priv); | 3688 | orinoco_uncache_fw(priv); |
| 3678 | 3689 | ||
| 3679 | priv->wpa_ie_len = 0; | 3690 | priv->wpa_ie_len = 0; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 22bc07ef2f3..f4747a1134b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
| @@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 48 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, | 48 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, |
| 49 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, | 49 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, |
| 50 | {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, | 50 | {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, |
| 51 | /* Surecom */ | ||
| 52 | {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, | ||
| 53 | /* Logitech */ | ||
| 54 | {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, | ||
| 51 | /* Netgear */ | 55 | /* Netgear */ |
| 52 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, | 56 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, |
| 53 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, | 57 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, |
| @@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 57 | /* Sitecom */ | 61 | /* Sitecom */ |
| 58 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, | 62 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
| 59 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, | 63 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, |
| 64 | /* Sphairon Access Systems GmbH */ | ||
| 65 | {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, | ||
| 66 | /* Dick Smith Electronics */ | ||
| 67 | {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, | ||
| 60 | /* Abocom */ | 68 | /* Abocom */ |
| 61 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, | 69 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, |
| 70 | /* Qcom */ | ||
| 71 | {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, | ||
| 72 | /* AirLive */ | ||
| 73 | {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, | ||
| 62 | {} | 74 | {} |
| 63 | }; | 75 | }; |
| 64 | 76 | ||
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index f5a662a50ac..26c536b51c5 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
| @@ -330,6 +330,14 @@ parse_dmar_table(void) | |||
| 330 | entry_header = (struct acpi_dmar_header *)(dmar + 1); | 330 | entry_header = (struct acpi_dmar_header *)(dmar + 1); |
| 331 | while (((unsigned long)entry_header) < | 331 | while (((unsigned long)entry_header) < |
| 332 | (((unsigned long)dmar) + dmar_tbl->length)) { | 332 | (((unsigned long)dmar) + dmar_tbl->length)) { |
| 333 | /* Avoid looping forever on bad ACPI tables */ | ||
| 334 | if (entry_header->length == 0) { | ||
| 335 | printk(KERN_WARNING PREFIX | ||
| 336 | "Invalid 0-length structure\n"); | ||
| 337 | ret = -EINVAL; | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | |||
| 333 | dmar_table_print_dmar_entry(entry_header); | 341 | dmar_table_print_dmar_entry(entry_header); |
| 334 | 342 | ||
| 335 | switch (entry_header->type) { | 343 | switch (entry_header->type) { |
| @@ -491,7 +499,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
| 491 | int map_size; | 499 | int map_size; |
| 492 | u32 ver; | 500 | u32 ver; |
| 493 | static int iommu_allocated = 0; | 501 | static int iommu_allocated = 0; |
| 494 | int agaw; | 502 | int agaw = 0; |
| 495 | 503 | ||
| 496 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | 504 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); |
| 497 | if (!iommu) | 505 | if (!iommu) |
| @@ -507,6 +515,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
| 507 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); | 515 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); |
| 508 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); | 516 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); |
| 509 | 517 | ||
| 518 | #ifdef CONFIG_DMAR | ||
| 510 | agaw = iommu_calculate_agaw(iommu); | 519 | agaw = iommu_calculate_agaw(iommu); |
| 511 | if (agaw < 0) { | 520 | if (agaw < 0) { |
| 512 | printk(KERN_ERR | 521 | printk(KERN_ERR |
| @@ -514,6 +523,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
| 514 | iommu->seq_id); | 523 | iommu->seq_id); |
| 515 | goto error; | 524 | goto error; |
| 516 | } | 525 | } |
| 526 | #endif | ||
| 517 | iommu->agaw = agaw; | 527 | iommu->agaw = agaw; |
| 518 | 528 | ||
| 519 | /* the registers might be more than one page */ | 529 | /* the registers might be more than one page */ |
| @@ -571,19 +581,49 @@ static inline void reclaim_free_desc(struct q_inval *qi) | |||
| 571 | } | 581 | } |
| 572 | } | 582 | } |
| 573 | 583 | ||
| 584 | static int qi_check_fault(struct intel_iommu *iommu, int index) | ||
| 585 | { | ||
| 586 | u32 fault; | ||
| 587 | int head; | ||
| 588 | struct q_inval *qi = iommu->qi; | ||
| 589 | int wait_index = (index + 1) % QI_LENGTH; | ||
| 590 | |||
| 591 | fault = readl(iommu->reg + DMAR_FSTS_REG); | ||
| 592 | |||
| 593 | /* | ||
| 594 | * If IQE happens, the head points to the descriptor associated | ||
| 595 | * with the error. No new descriptors are fetched until the IQE | ||
| 596 | * is cleared. | ||
| 597 | */ | ||
| 598 | if (fault & DMA_FSTS_IQE) { | ||
| 599 | head = readl(iommu->reg + DMAR_IQH_REG); | ||
| 600 | if ((head >> 4) == index) { | ||
| 601 | memcpy(&qi->desc[index], &qi->desc[wait_index], | ||
| 602 | sizeof(struct qi_desc)); | ||
| 603 | __iommu_flush_cache(iommu, &qi->desc[index], | ||
| 604 | sizeof(struct qi_desc)); | ||
| 605 | writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG); | ||
| 606 | return -EINVAL; | ||
| 607 | } | ||
| 608 | } | ||
| 609 | |||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | |||
| 574 | /* | 613 | /* |
| 575 | * Submit the queued invalidation descriptor to the remapping | 614 | * Submit the queued invalidation descriptor to the remapping |
| 576 | * hardware unit and wait for its completion. | 615 | * hardware unit and wait for its completion. |
| 577 | */ | 616 | */ |
| 578 | void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | 617 | int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) |
| 579 | { | 618 | { |
| 619 | int rc = 0; | ||
| 580 | struct q_inval *qi = iommu->qi; | 620 | struct q_inval *qi = iommu->qi; |
| 581 | struct qi_desc *hw, wait_desc; | 621 | struct qi_desc *hw, wait_desc; |
| 582 | int wait_index, index; | 622 | int wait_index, index; |
| 583 | unsigned long flags; | 623 | unsigned long flags; |
| 584 | 624 | ||
| 585 | if (!qi) | 625 | if (!qi) |
| 586 | return; | 626 | return 0; |
| 587 | 627 | ||
| 588 | hw = qi->desc; | 628 | hw = qi->desc; |
| 589 | 629 | ||
| @@ -601,7 +641,8 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
| 601 | 641 | ||
| 602 | hw[index] = *desc; | 642 | hw[index] = *desc; |
| 603 | 643 | ||
| 604 | wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; | 644 | wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) | |
| 645 | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; | ||
| 605 | wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]); | 646 | wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]); |
| 606 | 647 | ||
| 607 | hw[wait_index] = wait_desc; | 648 | hw[wait_index] = wait_desc; |
| @@ -612,13 +653,11 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
| 612 | qi->free_head = (qi->free_head + 2) % QI_LENGTH; | 653 | qi->free_head = (qi->free_head + 2) % QI_LENGTH; |
| 613 | qi->free_cnt -= 2; | 654 | qi->free_cnt -= 2; |
| 614 | 655 | ||
| 615 | spin_lock(&iommu->register_lock); | ||
| 616 | /* | 656 | /* |
| 617 | * update the HW tail register indicating the presence of | 657 | * update the HW tail register indicating the presence of |
| 618 | * new descriptors. | 658 | * new descriptors. |
| 619 | */ | 659 | */ |
| 620 | writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); | 660 | writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); |
| 621 | spin_unlock(&iommu->register_lock); | ||
| 622 | 661 | ||
| 623 | while (qi->desc_status[wait_index] != QI_DONE) { | 662 | while (qi->desc_status[wait_index] != QI_DONE) { |
| 624 | /* | 663 | /* |
| @@ -628,15 +667,21 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
| 628 | * a deadlock where the interrupt context can wait indefinitely | 667 | * a deadlock where the interrupt context can wait indefinitely |
| 629 | * for free slots in the queue. | 668 | * for free slots in the queue. |
| 630 | */ | 669 | */ |
| 670 | rc = qi_check_fault(iommu, index); | ||
| 671 | if (rc) | ||
| 672 | goto out; | ||
| 673 | |||
| 631 | spin_unlock(&qi->q_lock); | 674 | spin_unlock(&qi->q_lock); |
| 632 | cpu_relax(); | 675 | cpu_relax(); |
| 633 | spin_lock(&qi->q_lock); | 676 | spin_lock(&qi->q_lock); |
| 634 | } | 677 | } |
| 635 | 678 | out: | |
| 636 | qi->desc_status[index] = QI_DONE; | 679 | qi->desc_status[index] = qi->desc_status[wait_index] = QI_DONE; |
| 637 | 680 | ||
| 638 | reclaim_free_desc(qi); | 681 | reclaim_free_desc(qi); |
| 639 | spin_unlock_irqrestore(&qi->q_lock, flags); | 682 | spin_unlock_irqrestore(&qi->q_lock, flags); |
| 683 | |||
| 684 | return rc; | ||
| 640 | } | 685 | } |
| 641 | 686 | ||
| 642 | /* | 687 | /* |
| @@ -649,13 +694,13 @@ void qi_global_iec(struct intel_iommu *iommu) | |||
| 649 | desc.low = QI_IEC_TYPE; | 694 | desc.low = QI_IEC_TYPE; |
| 650 | desc.high = 0; | 695 | desc.high = 0; |
| 651 | 696 | ||
| 697 | /* should never fail */ | ||
| 652 | qi_submit_sync(&desc, iommu); | 698 | qi_submit_sync(&desc, iommu); |
| 653 | } | 699 | } |
| 654 | 700 | ||
| 655 | int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, | 701 | int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, |
| 656 | u64 type, int non_present_entry_flush) | 702 | u64 type, int non_present_entry_flush) |
| 657 | { | 703 | { |
| 658 | |||
| 659 | struct qi_desc desc; | 704 | struct qi_desc desc; |
| 660 | 705 | ||
| 661 | if (non_present_entry_flush) { | 706 | if (non_present_entry_flush) { |
| @@ -669,10 +714,7 @@ int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, | |||
| 669 | | QI_CC_GRAN(type) | QI_CC_TYPE; | 714 | | QI_CC_GRAN(type) | QI_CC_TYPE; |
| 670 | desc.high = 0; | 715 | desc.high = 0; |
| 671 | 716 | ||
| 672 | qi_submit_sync(&desc, iommu); | 717 | return qi_submit_sync(&desc, iommu); |
| 673 | |||
| 674 | return 0; | ||
| 675 | |||
| 676 | } | 718 | } |
| 677 | 719 | ||
| 678 | int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | 720 | int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, |
| @@ -702,10 +744,7 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | |||
| 702 | desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih) | 744 | desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih) |
| 703 | | QI_IOTLB_AM(size_order); | 745 | | QI_IOTLB_AM(size_order); |
| 704 | 746 | ||
| 705 | qi_submit_sync(&desc, iommu); | 747 | return qi_submit_sync(&desc, iommu); |
| 706 | |||
| 707 | return 0; | ||
| 708 | |||
| 709 | } | 748 | } |
| 710 | 749 | ||
| 711 | /* | 750 | /* |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index db85284ffb6..39ae37589fd 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -111,6 +111,7 @@ struct controller { | |||
| 111 | int cmd_busy; | 111 | int cmd_busy; |
| 112 | unsigned int no_cmd_complete:1; | 112 | unsigned int no_cmd_complete:1; |
| 113 | unsigned int link_active_reporting:1; | 113 | unsigned int link_active_reporting:1; |
| 114 | unsigned int notification_enabled:1; | ||
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | #define INT_BUTTON_IGNORE 0 | 117 | #define INT_BUTTON_IGNORE 0 |
| @@ -170,6 +171,7 @@ extern int pciehp_configure_device(struct slot *p_slot); | |||
| 170 | extern int pciehp_unconfigure_device(struct slot *p_slot); | 171 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
| 171 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); | 172 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); |
| 172 | struct controller *pcie_init(struct pcie_device *dev); | 173 | struct controller *pcie_init(struct pcie_device *dev); |
| 174 | int pcie_init_notification(struct controller *ctrl); | ||
| 173 | int pciehp_enable_slot(struct slot *p_slot); | 175 | int pciehp_enable_slot(struct slot *p_slot); |
| 174 | int pciehp_disable_slot(struct slot *p_slot); | 176 | int pciehp_disable_slot(struct slot *p_slot); |
| 175 | int pcie_enable_notification(struct controller *ctrl); | 177 | int pcie_enable_notification(struct controller *ctrl); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c2485542f54..681e3912b82 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -434,6 +434,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 434 | goto err_out_release_ctlr; | 434 | goto err_out_release_ctlr; |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | /* Enable events after we have setup the data structures */ | ||
| 438 | rc = pcie_init_notification(ctrl); | ||
| 439 | if (rc) { | ||
| 440 | ctrl_err(ctrl, "Notification initialization failed\n"); | ||
| 441 | goto err_out_release_ctlr; | ||
| 442 | } | ||
| 443 | |||
| 437 | /* Check if slot is occupied */ | 444 | /* Check if slot is occupied */ |
| 438 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 445 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
| 439 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); | 446 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 71a8012886b..7a16c6897bb 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -934,7 +934,7 @@ static void pcie_disable_notification(struct controller *ctrl) | |||
| 934 | ctrl_warn(ctrl, "Cannot disable software notification\n"); | 934 | ctrl_warn(ctrl, "Cannot disable software notification\n"); |
| 935 | } | 935 | } |
| 936 | 936 | ||
| 937 | static int pcie_init_notification(struct controller *ctrl) | 937 | int pcie_init_notification(struct controller *ctrl) |
| 938 | { | 938 | { |
| 939 | if (pciehp_request_irq(ctrl)) | 939 | if (pciehp_request_irq(ctrl)) |
| 940 | return -1; | 940 | return -1; |
| @@ -942,13 +942,17 @@ static int pcie_init_notification(struct controller *ctrl) | |||
| 942 | pciehp_free_irq(ctrl); | 942 | pciehp_free_irq(ctrl); |
| 943 | return -1; | 943 | return -1; |
| 944 | } | 944 | } |
| 945 | ctrl->notification_enabled = 1; | ||
| 945 | return 0; | 946 | return 0; |
| 946 | } | 947 | } |
| 947 | 948 | ||
| 948 | static void pcie_shutdown_notification(struct controller *ctrl) | 949 | static void pcie_shutdown_notification(struct controller *ctrl) |
| 949 | { | 950 | { |
| 950 | pcie_disable_notification(ctrl); | 951 | if (ctrl->notification_enabled) { |
| 951 | pciehp_free_irq(ctrl); | 952 | pcie_disable_notification(ctrl); |
| 953 | pciehp_free_irq(ctrl); | ||
| 954 | ctrl->notification_enabled = 0; | ||
| 955 | } | ||
| 952 | } | 956 | } |
| 953 | 957 | ||
| 954 | static int pcie_init_slot(struct controller *ctrl) | 958 | static int pcie_init_slot(struct controller *ctrl) |
| @@ -1110,13 +1114,8 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
| 1110 | if (pcie_init_slot(ctrl)) | 1114 | if (pcie_init_slot(ctrl)) |
| 1111 | goto abort_ctrl; | 1115 | goto abort_ctrl; |
| 1112 | 1116 | ||
| 1113 | if (pcie_init_notification(ctrl)) | ||
| 1114 | goto abort_slot; | ||
| 1115 | |||
| 1116 | return ctrl; | 1117 | return ctrl; |
| 1117 | 1118 | ||
| 1118 | abort_slot: | ||
| 1119 | pcie_cleanup_slot(ctrl); | ||
| 1120 | abort_ctrl: | 1119 | abort_ctrl: |
| 1121 | kfree(ctrl); | 1120 | kfree(ctrl); |
| 1122 | abort: | 1121 | abort: |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f78371b2252..45effc5726c 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
| @@ -207,7 +207,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
| 207 | return index; | 207 | return index; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask) | 210 | static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask) |
| 211 | { | 211 | { |
| 212 | struct qi_desc desc; | 212 | struct qi_desc desc; |
| 213 | 213 | ||
| @@ -215,7 +215,7 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask) | |||
| 215 | | QI_IEC_SELECTIVE; | 215 | | QI_IEC_SELECTIVE; |
| 216 | desc.high = 0; | 216 | desc.high = 0; |
| 217 | 217 | ||
| 218 | qi_submit_sync(&desc, iommu); | 218 | return qi_submit_sync(&desc, iommu); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) | 221 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) |
| @@ -283,6 +283,7 @@ int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index) | |||
| 283 | 283 | ||
| 284 | int modify_irte(int irq, struct irte *irte_modified) | 284 | int modify_irte(int irq, struct irte *irte_modified) |
| 285 | { | 285 | { |
| 286 | int rc; | ||
| 286 | int index; | 287 | int index; |
| 287 | struct irte *irte; | 288 | struct irte *irte; |
| 288 | struct intel_iommu *iommu; | 289 | struct intel_iommu *iommu; |
| @@ -303,14 +304,15 @@ int modify_irte(int irq, struct irte *irte_modified) | |||
| 303 | set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); | 304 | set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); |
| 304 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); | 305 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); |
| 305 | 306 | ||
| 306 | qi_flush_iec(iommu, index, 0); | 307 | rc = qi_flush_iec(iommu, index, 0); |
| 307 | |||
| 308 | spin_unlock(&irq_2_ir_lock); | 308 | spin_unlock(&irq_2_ir_lock); |
| 309 | return 0; | 309 | |
| 310 | return rc; | ||
| 310 | } | 311 | } |
| 311 | 312 | ||
| 312 | int flush_irte(int irq) | 313 | int flush_irte(int irq) |
| 313 | { | 314 | { |
| 315 | int rc; | ||
| 314 | int index; | 316 | int index; |
| 315 | struct intel_iommu *iommu; | 317 | struct intel_iommu *iommu; |
| 316 | struct irq_2_iommu *irq_iommu; | 318 | struct irq_2_iommu *irq_iommu; |
| @@ -326,10 +328,10 @@ int flush_irte(int irq) | |||
| 326 | 328 | ||
| 327 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | 329 | index = irq_iommu->irte_index + irq_iommu->sub_handle; |
| 328 | 330 | ||
| 329 | qi_flush_iec(iommu, index, irq_iommu->irte_mask); | 331 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); |
| 330 | spin_unlock(&irq_2_ir_lock); | 332 | spin_unlock(&irq_2_ir_lock); |
| 331 | 333 | ||
| 332 | return 0; | 334 | return rc; |
| 333 | } | 335 | } |
| 334 | 336 | ||
| 335 | struct intel_iommu *map_ioapic_to_ir(int apic) | 337 | struct intel_iommu *map_ioapic_to_ir(int apic) |
| @@ -355,6 +357,7 @@ struct intel_iommu *map_dev_to_ir(struct pci_dev *dev) | |||
| 355 | 357 | ||
| 356 | int free_irte(int irq) | 358 | int free_irte(int irq) |
| 357 | { | 359 | { |
| 360 | int rc = 0; | ||
| 358 | int index, i; | 361 | int index, i; |
| 359 | struct irte *irte; | 362 | struct irte *irte; |
| 360 | struct intel_iommu *iommu; | 363 | struct intel_iommu *iommu; |
| @@ -375,7 +378,7 @@ int free_irte(int irq) | |||
| 375 | if (!irq_iommu->sub_handle) { | 378 | if (!irq_iommu->sub_handle) { |
| 376 | for (i = 0; i < (1 << irq_iommu->irte_mask); i++) | 379 | for (i = 0; i < (1 << irq_iommu->irte_mask); i++) |
| 377 | set_64bit((unsigned long *)irte, 0); | 380 | set_64bit((unsigned long *)irte, 0); |
| 378 | qi_flush_iec(iommu, index, irq_iommu->irte_mask); | 381 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); |
| 379 | } | 382 | } |
| 380 | 383 | ||
| 381 | irq_iommu->iommu = NULL; | 384 | irq_iommu->iommu = NULL; |
| @@ -385,7 +388,7 @@ int free_irte(int irq) | |||
| 385 | 388 | ||
| 386 | spin_unlock(&irq_2_ir_lock); | 389 | spin_unlock(&irq_2_ir_lock); |
| 387 | 390 | ||
| 388 | return 0; | 391 | return rc; |
| 389 | } | 392 | } |
| 390 | 393 | ||
| 391 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | 394 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index aac7006949f..d0c97368586 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
| @@ -108,6 +108,34 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) | |||
| 108 | } | 108 | } |
| 109 | #endif /* 0 */ | 109 | #endif /* 0 */ |
| 110 | 110 | ||
| 111 | |||
| 112 | static void set_device_error_reporting(struct pci_dev *dev, void *data) | ||
| 113 | { | ||
| 114 | bool enable = *((bool *)data); | ||
| 115 | |||
| 116 | if (dev->pcie_type != PCIE_RC_PORT && | ||
| 117 | dev->pcie_type != PCIE_SW_UPSTREAM_PORT && | ||
| 118 | dev->pcie_type != PCIE_SW_DOWNSTREAM_PORT) | ||
| 119 | return; | ||
| 120 | |||
| 121 | if (enable) | ||
| 122 | pci_enable_pcie_error_reporting(dev); | ||
| 123 | else | ||
| 124 | pci_disable_pcie_error_reporting(dev); | ||
| 125 | } | ||
| 126 | |||
| 127 | /** | ||
| 128 | * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports. | ||
| 129 | * @dev: pointer to root port's pci_dev data structure | ||
| 130 | * @enable: true = enable error reporting, false = disable error reporting. | ||
| 131 | */ | ||
| 132 | static void set_downstream_devices_error_reporting(struct pci_dev *dev, | ||
| 133 | bool enable) | ||
| 134 | { | ||
| 135 | set_device_error_reporting(dev, &enable); | ||
| 136 | pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); | ||
| 137 | } | ||
| 138 | |||
| 111 | static int find_device_iter(struct device *device, void *data) | 139 | static int find_device_iter(struct device *device, void *data) |
| 112 | { | 140 | { |
| 113 | struct pci_dev *dev; | 141 | struct pci_dev *dev; |
| @@ -525,15 +553,11 @@ void aer_enable_rootport(struct aer_rpc *rpc) | |||
| 525 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); | 553 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); |
| 526 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); | 554 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); |
| 527 | 555 | ||
| 528 | /* Enable Root Port device reporting error itself */ | 556 | /* |
| 529 | pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, ®16); | 557 | * Enable error reporting for the root port device and downstream port |
| 530 | reg16 = reg16 | | 558 | * devices. |
| 531 | PCI_EXP_DEVCTL_CERE | | 559 | */ |
| 532 | PCI_EXP_DEVCTL_NFERE | | 560 | set_downstream_devices_error_reporting(pdev, true); |
| 533 | PCI_EXP_DEVCTL_FERE | | ||
| 534 | PCI_EXP_DEVCTL_URRE; | ||
| 535 | pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL, | ||
| 536 | reg16); | ||
| 537 | 561 | ||
| 538 | /* Enable Root Port's interrupt in response to error messages */ | 562 | /* Enable Root Port's interrupt in response to error messages */ |
| 539 | pci_write_config_dword(pdev, | 563 | pci_write_config_dword(pdev, |
| @@ -553,6 +577,12 @@ static void disable_root_aer(struct aer_rpc *rpc) | |||
| 553 | u32 reg32; | 577 | u32 reg32; |
| 554 | int pos; | 578 | int pos; |
| 555 | 579 | ||
| 580 | /* | ||
| 581 | * Disable error reporting for the root port device and downstream port | ||
| 582 | * devices. | ||
| 583 | */ | ||
| 584 | set_downstream_devices_error_reporting(pdev, false); | ||
| 585 | |||
| 556 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 586 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); |
| 557 | /* Disable Root's interrupt in response to error messages */ | 587 | /* Disable Root's interrupt in response to error messages */ |
| 558 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); | 588 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f9b874eaeb9..248b4db9155 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -97,8 +97,6 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, | |||
| 97 | 97 | ||
| 98 | pcie_portdrv_save_config(dev); | 98 | pcie_portdrv_save_config(dev); |
| 99 | 99 | ||
| 100 | pci_enable_pcie_error_reporting(dev); | ||
| 101 | |||
| 102 | return 0; | 100 | return 0; |
| 103 | } | 101 | } |
| 104 | 102 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index baad093aafe..f20d55368ed 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -1584,6 +1584,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_ | |||
| 1584 | */ | 1584 | */ |
| 1585 | #define AMD_813X_MISC 0x40 | 1585 | #define AMD_813X_MISC 0x40 |
| 1586 | #define AMD_813X_NOIOAMODE (1<<0) | 1586 | #define AMD_813X_NOIOAMODE (1<<0) |
| 1587 | #define AMD_813X_REV_B2 0x13 | ||
| 1587 | 1588 | ||
| 1588 | static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | 1589 | static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) |
| 1589 | { | 1590 | { |
| @@ -1591,6 +1592,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | |||
| 1591 | 1592 | ||
| 1592 | if (noioapicquirk) | 1593 | if (noioapicquirk) |
| 1593 | return; | 1594 | return; |
| 1595 | if (dev->revision == AMD_813X_REV_B2) | ||
| 1596 | return; | ||
| 1594 | 1597 | ||
| 1595 | pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); | 1598 | pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); |
| 1596 | pci_config_dword &= ~AMD_813X_NOIOAMODE; | 1599 | pci_config_dword &= ~AMD_813X_NOIOAMODE; |
| @@ -1981,7 +1984,6 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev) | |||
| 1981 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, | 1984 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, |
| 1982 | quirk_msi_ht_cap); | 1985 | quirk_msi_ht_cap); |
| 1983 | 1986 | ||
| 1984 | |||
| 1985 | /* The nVidia CK804 chipset may have 2 HT MSI mappings. | 1987 | /* The nVidia CK804 chipset may have 2 HT MSI mappings. |
| 1986 | * MSI are supported if the MSI capability set in any of these mappings. | 1988 | * MSI are supported if the MSI capability set in any of these mappings. |
| 1987 | */ | 1989 | */ |
| @@ -2032,6 +2034,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, | |||
| 2032 | PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, | 2034 | PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, |
| 2033 | ht_enable_msi_mapping); | 2035 | ht_enable_msi_mapping); |
| 2034 | 2036 | ||
| 2037 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, | ||
| 2038 | ht_enable_msi_mapping); | ||
| 2039 | |||
| 2035 | /* The P5N32-SLI Premium motherboard from Asus has a problem with msi | 2040 | /* The P5N32-SLI Premium motherboard from Asus has a problem with msi |
| 2036 | * for the MCP55 NIC. It is not yet determined whether the msi problem | 2041 | * for the MCP55 NIC. It is not yet determined whether the msi problem |
| 2037 | * also affects other devices. As for now, turn off msi for this device. | 2042 | * also affects other devices. As for now, turn off msi for this device. |
| @@ -2048,10 +2053,100 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, | |||
| 2048 | PCI_DEVICE_ID_NVIDIA_NVENET_15, | 2053 | PCI_DEVICE_ID_NVIDIA_NVENET_15, |
| 2049 | nvenet_msi_disable); | 2054 | nvenet_msi_disable); |
| 2050 | 2055 | ||
| 2051 | static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | 2056 | static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) |
| 2052 | { | 2057 | { |
| 2053 | struct pci_dev *host_bridge; | 2058 | struct pci_dev *host_bridge; |
| 2059 | int pos; | ||
| 2060 | int i, dev_no; | ||
| 2061 | int found = 0; | ||
| 2062 | |||
| 2063 | dev_no = dev->devfn >> 3; | ||
| 2064 | for (i = dev_no; i >= 0; i--) { | ||
| 2065 | host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0)); | ||
| 2066 | if (!host_bridge) | ||
| 2067 | continue; | ||
| 2068 | |||
| 2069 | pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); | ||
| 2070 | if (pos != 0) { | ||
| 2071 | found = 1; | ||
| 2072 | break; | ||
| 2073 | } | ||
| 2074 | pci_dev_put(host_bridge); | ||
| 2075 | } | ||
| 2076 | |||
| 2077 | if (!found) | ||
| 2078 | return; | ||
| 2079 | |||
| 2080 | /* root did that ! */ | ||
| 2081 | if (msi_ht_cap_enabled(host_bridge)) | ||
| 2082 | goto out; | ||
| 2083 | |||
| 2084 | ht_enable_msi_mapping(dev); | ||
| 2085 | |||
| 2086 | out: | ||
| 2087 | pci_dev_put(host_bridge); | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) | ||
| 2091 | { | ||
| 2092 | int pos, ttl = 48; | ||
| 2093 | |||
| 2094 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); | ||
| 2095 | while (pos && ttl--) { | ||
| 2096 | u8 flags; | ||
| 2097 | |||
| 2098 | if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, | ||
| 2099 | &flags) == 0) { | ||
| 2100 | dev_info(&dev->dev, "Enabling HT MSI Mapping\n"); | ||
| 2101 | |||
| 2102 | pci_write_config_byte(dev, pos + HT_MSI_FLAGS, | ||
| 2103 | flags & ~HT_MSI_FLAGS_ENABLE); | ||
| 2104 | } | ||
| 2105 | pos = pci_find_next_ht_capability(dev, pos, | ||
| 2106 | HT_CAPTYPE_MSI_MAPPING); | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | static int __devinit ht_check_msi_mapping(struct pci_dev *dev) | ||
| 2111 | { | ||
| 2054 | int pos, ttl = 48; | 2112 | int pos, ttl = 48; |
| 2113 | int found = 0; | ||
| 2114 | |||
| 2115 | /* check if there is HT MSI cap or enabled on this device */ | ||
| 2116 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); | ||
| 2117 | while (pos && ttl--) { | ||
| 2118 | u8 flags; | ||
| 2119 | |||
| 2120 | if (found < 1) | ||
| 2121 | found = 1; | ||
| 2122 | if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, | ||
| 2123 | &flags) == 0) { | ||
| 2124 | if (flags & HT_MSI_FLAGS_ENABLE) { | ||
| 2125 | if (found < 2) { | ||
| 2126 | found = 2; | ||
| 2127 | break; | ||
| 2128 | } | ||
| 2129 | } | ||
| 2130 | } | ||
| 2131 | pos = pci_find_next_ht_capability(dev, pos, | ||
| 2132 | HT_CAPTYPE_MSI_MAPPING); | ||
| 2133 | } | ||
| 2134 | |||
| 2135 | return found; | ||
| 2136 | } | ||
| 2137 | |||
| 2138 | static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | ||
| 2139 | { | ||
| 2140 | struct pci_dev *host_bridge; | ||
| 2141 | int pos; | ||
| 2142 | int found; | ||
| 2143 | |||
| 2144 | /* check if there is HT MSI cap or enabled on this device */ | ||
| 2145 | found = ht_check_msi_mapping(dev); | ||
| 2146 | |||
| 2147 | /* no HT MSI CAP */ | ||
| 2148 | if (found == 0) | ||
| 2149 | return; | ||
| 2055 | 2150 | ||
| 2056 | /* | 2151 | /* |
| 2057 | * HT MSI mapping should be disabled on devices that are below | 2152 | * HT MSI mapping should be disabled on devices that are below |
| @@ -2067,24 +2162,19 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | |||
| 2067 | pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); | 2162 | pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); |
| 2068 | if (pos != 0) { | 2163 | if (pos != 0) { |
| 2069 | /* Host bridge is to HT */ | 2164 | /* Host bridge is to HT */ |
| 2070 | ht_enable_msi_mapping(dev); | 2165 | if (found == 1) { |
| 2166 | /* it is not enabled, try to enable it */ | ||
| 2167 | nv_ht_enable_msi_mapping(dev); | ||
| 2168 | } | ||
| 2071 | return; | 2169 | return; |
| 2072 | } | 2170 | } |
| 2073 | 2171 | ||
| 2074 | /* Host bridge is not to HT, disable HT MSI mapping on this device */ | 2172 | /* HT MSI is not enabled */ |
| 2075 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); | 2173 | if (found == 1) |
| 2076 | while (pos && ttl--) { | 2174 | return; |
| 2077 | u8 flags; | ||
| 2078 | 2175 | ||
| 2079 | if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, | 2176 | /* Host bridge is not to HT, disable HT MSI mapping on this device */ |
| 2080 | &flags) == 0) { | 2177 | ht_disable_msi_mapping(dev); |
| 2081 | dev_info(&dev->dev, "Disabling HT MSI mapping"); | ||
| 2082 | pci_write_config_byte(dev, pos + HT_MSI_FLAGS, | ||
| 2083 | flags & ~HT_MSI_FLAGS_ENABLE); | ||
| 2084 | } | ||
| 2085 | pos = pci_find_next_ht_capability(dev, pos, | ||
| 2086 | HT_CAPTYPE_MSI_MAPPING); | ||
| 2087 | } | ||
| 2088 | } | 2178 | } |
| 2089 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); | 2179 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); |
| 2090 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); | 2180 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); |
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index fde6e4c634e..a7cf550b9cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
| 22 | #include <linux/scatterlist.h> | 22 | #include <linux/scatterlist.h> |
| 23 | #include <linux/skbuff.h> | ||
| 23 | #include <scsi/libiscsi_tcp.h> | 24 | #include <scsi/libiscsi_tcp.h> |
| 24 | 25 | ||
| 25 | /* from cxgb3 LLD */ | 26 | /* from cxgb3 LLD */ |
| @@ -113,6 +114,26 @@ struct cxgb3i_endpoint { | |||
| 113 | struct cxgb3i_conn *cconn; | 114 | struct cxgb3i_conn *cconn; |
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 117 | /** | ||
| 118 | * struct cxgb3i_task_data - private iscsi task data | ||
| 119 | * | ||
| 120 | * @nr_frags: # of coalesced page frags (from scsi sgl) | ||
| 121 | * @frags: coalesced page frags (from scsi sgl) | ||
| 122 | * @skb: tx pdu skb | ||
| 123 | * @offset: data offset for the next pdu | ||
| 124 | * @count: max. possible pdu payload | ||
| 125 | * @sgoffset: offset to the first sg entry for a given offset | ||
| 126 | */ | ||
| 127 | #define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) | ||
| 128 | struct cxgb3i_task_data { | ||
| 129 | unsigned short nr_frags; | ||
| 130 | skb_frag_t frags[MAX_PDU_FRAGS]; | ||
| 131 | struct sk_buff *skb; | ||
| 132 | unsigned int offset; | ||
| 133 | unsigned int count; | ||
| 134 | unsigned int sgoffset; | ||
| 135 | }; | ||
| 136 | |||
| 116 | int cxgb3i_iscsi_init(void); | 137 | int cxgb3i_iscsi_init(void); |
| 117 | void cxgb3i_iscsi_cleanup(void); | 138 | void cxgb3i_iscsi_cleanup(void); |
| 118 | 139 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 08f3a09d923..a83d36e4926 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c | |||
| @@ -639,10 +639,11 @@ static int ddp_init(struct t3cdev *tdev) | |||
| 639 | write_unlock(&cxgb3i_ddp_rwlock); | 639 | write_unlock(&cxgb3i_ddp_rwlock); |
| 640 | 640 | ||
| 641 | ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " | 641 | ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " |
| 642 | "pkt %u,%u.\n", | 642 | "pkt %u/%u, %u/%u.\n", |
| 643 | ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, | 643 | ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, |
| 644 | ddp->idx_mask, ddp->rsvd_tag_mask, | 644 | ddp->idx_mask, ddp->rsvd_tag_mask, |
| 645 | ddp->max_txsz, ddp->max_rxsz); | 645 | ddp->max_txsz, uinfo.max_txsz, |
| 646 | ddp->max_rxsz, uinfo.max_rxsz); | ||
| 646 | return 0; | 647 | return 0; |
| 647 | 648 | ||
| 648 | free_ddp_map: | 649 | free_ddp_map: |
| @@ -654,8 +655,8 @@ free_ddp_map: | |||
| 654 | * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource | 655 | * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource |
| 655 | * @tdev: t3cdev adapter | 656 | * @tdev: t3cdev adapter |
| 656 | * @tformat: tag format | 657 | * @tformat: tag format |
| 657 | * @txsz: max tx pkt size, filled in by this func. | 658 | * @txsz: max tx pdu payload size, filled in by this func. |
| 658 | * @rxsz: max rx pkt size, filled in by this func. | 659 | * @rxsz: max rx pdu payload size, filled in by this func. |
| 659 | * initialize the ddp pagepod manager for a given adapter if needed and | 660 | * initialize the ddp pagepod manager for a given adapter if needed and |
| 660 | * setup the tag format for a given iscsi entity | 661 | * setup the tag format for a given iscsi entity |
| 661 | */ | 662 | */ |
| @@ -685,10 +686,12 @@ int cxgb3i_adapter_ddp_init(struct t3cdev *tdev, | |||
| 685 | tformat->sw_bits, tformat->rsvd_bits, | 686 | tformat->sw_bits, tformat->rsvd_bits, |
| 686 | tformat->rsvd_shift, tformat->rsvd_mask); | 687 | tformat->rsvd_shift, tformat->rsvd_mask); |
| 687 | 688 | ||
| 688 | *txsz = ddp->max_txsz; | 689 | *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, |
| 689 | *rxsz = ddp->max_rxsz; | 690 | ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN); |
| 690 | ddp_log_info("ddp max pkt size: %u, %u.\n", | 691 | *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, |
| 691 | ddp->max_txsz, ddp->max_rxsz); | 692 | ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN); |
| 693 | ddp_log_info("max payload size: %u/%u, %u/%u.\n", | ||
| 694 | *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz); | ||
| 692 | return 0; | 695 | return 0; |
| 693 | } | 696 | } |
| 694 | EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); | 697 | EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 5c7c4d95c49..3faae7831c8 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #ifndef __CXGB3I_ULP2_DDP_H__ | 13 | #ifndef __CXGB3I_ULP2_DDP_H__ |
| 14 | #define __CXGB3I_ULP2_DDP_H__ | 14 | #define __CXGB3I_ULP2_DDP_H__ |
| 15 | 15 | ||
| 16 | #include <linux/vmalloc.h> | ||
| 17 | |||
| 16 | /** | 18 | /** |
| 17 | * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity | 19 | * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity |
| 18 | * | 20 | * |
| @@ -85,8 +87,9 @@ struct cxgb3i_ddp_info { | |||
| 85 | struct sk_buff **gl_skb; | 87 | struct sk_buff **gl_skb; |
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| 90 | #define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */ | ||
| 88 | #define ULP2_MAX_PKT_SIZE 16224 | 91 | #define ULP2_MAX_PKT_SIZE 16224 |
| 89 | #define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX) | 92 | #define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN) |
| 90 | #define PPOD_PAGES_MAX 4 | 93 | #define PPOD_PAGES_MAX 4 |
| 91 | #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ | 94 | #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ |
| 92 | 95 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c index 091ecb4d9f3..1ce9f244e46 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_init.c +++ b/drivers/scsi/cxgb3i/cxgb3i_init.c | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "cxgb3i.h" | 12 | #include "cxgb3i.h" |
| 13 | 13 | ||
| 14 | #define DRV_MODULE_NAME "cxgb3i" | 14 | #define DRV_MODULE_NAME "cxgb3i" |
| 15 | #define DRV_MODULE_VERSION "1.0.0" | 15 | #define DRV_MODULE_VERSION "1.0.1" |
| 16 | #define DRV_MODULE_RELDATE "Jun. 1, 2008" | 16 | #define DRV_MODULE_RELDATE "Jan. 2009" |
| 17 | 17 | ||
| 18 | static char version[] = | 18 | static char version[] = |
| 19 | "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME | 19 | "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index d83464b9b3f..fa2a44f37b3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
| @@ -364,7 +364,8 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, | |||
| 364 | 364 | ||
| 365 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, | 365 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, |
| 366 | cmds_max, | 366 | cmds_max, |
| 367 | sizeof(struct iscsi_tcp_task), | 367 | sizeof(struct iscsi_tcp_task) + |
| 368 | sizeof(struct cxgb3i_task_data), | ||
| 368 | initial_cmdsn, ISCSI_MAX_TARGET); | 369 | initial_cmdsn, ISCSI_MAX_TARGET); |
| 369 | if (!cls_session) | 370 | if (!cls_session) |
| 370 | return NULL; | 371 | return NULL; |
| @@ -402,17 +403,15 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) | |||
| 402 | { | 403 | { |
| 403 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 404 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 404 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 405 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 405 | unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, | 406 | unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM); |
| 406 | cconn->hba->snic->tx_max_size - | ||
| 407 | ISCSI_PDU_NONPAYLOAD_MAX); | ||
| 408 | 407 | ||
| 408 | max = min(cconn->hba->snic->tx_max_size, max); | ||
| 409 | if (conn->max_xmit_dlength) | 409 | if (conn->max_xmit_dlength) |
| 410 | conn->max_xmit_dlength = min_t(unsigned int, | 410 | conn->max_xmit_dlength = min(conn->max_xmit_dlength, max); |
| 411 | conn->max_xmit_dlength, max); | ||
| 412 | else | 411 | else |
| 413 | conn->max_xmit_dlength = max; | 412 | conn->max_xmit_dlength = max; |
| 414 | align_pdu_size(conn->max_xmit_dlength); | 413 | align_pdu_size(conn->max_xmit_dlength); |
| 415 | cxgb3i_log_info("conn 0x%p, max xmit %u.\n", | 414 | cxgb3i_api_debug("conn 0x%p, max xmit %u.\n", |
| 416 | conn, conn->max_xmit_dlength); | 415 | conn, conn->max_xmit_dlength); |
| 417 | return 0; | 416 | return 0; |
| 418 | } | 417 | } |
| @@ -427,9 +426,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) | |||
| 427 | { | 426 | { |
| 428 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 427 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 429 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 428 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 430 | unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, | 429 | unsigned int max = cconn->hba->snic->rx_max_size; |
| 431 | cconn->hba->snic->rx_max_size - | ||
| 432 | ISCSI_PDU_NONPAYLOAD_MAX); | ||
| 433 | 430 | ||
| 434 | align_pdu_size(max); | 431 | align_pdu_size(max); |
| 435 | if (conn->max_recv_dlength) { | 432 | if (conn->max_recv_dlength) { |
| @@ -439,8 +436,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) | |||
| 439 | conn->max_recv_dlength, max); | 436 | conn->max_recv_dlength, max); |
| 440 | return -EINVAL; | 437 | return -EINVAL; |
| 441 | } | 438 | } |
| 442 | conn->max_recv_dlength = min_t(unsigned int, | 439 | conn->max_recv_dlength = min(conn->max_recv_dlength, max); |
| 443 | conn->max_recv_dlength, max); | ||
| 444 | align_pdu_size(conn->max_recv_dlength); | 440 | align_pdu_size(conn->max_recv_dlength); |
| 445 | } else | 441 | } else |
| 446 | conn->max_recv_dlength = max; | 442 | conn->max_recv_dlength = max; |
| @@ -844,7 +840,7 @@ static struct scsi_host_template cxgb3i_host_template = { | |||
| 844 | .proc_name = "cxgb3i", | 840 | .proc_name = "cxgb3i", |
| 845 | .queuecommand = iscsi_queuecommand, | 841 | .queuecommand = iscsi_queuecommand, |
| 846 | .change_queue_depth = iscsi_change_queue_depth, | 842 | .change_queue_depth = iscsi_change_queue_depth, |
| 847 | .can_queue = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1), | 843 | .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, |
| 848 | .sg_tablesize = SG_ALL, | 844 | .sg_tablesize = SG_ALL, |
| 849 | .max_sectors = 0xFFFF, | 845 | .max_sectors = 0xFFFF, |
| 850 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, | 846 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a865f1fefe8..de3b3b614cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c | |||
| @@ -23,19 +23,19 @@ | |||
| 23 | #include "cxgb3i_ddp.h" | 23 | #include "cxgb3i_ddp.h" |
| 24 | 24 | ||
| 25 | #ifdef __DEBUG_C3CN_CONN__ | 25 | #ifdef __DEBUG_C3CN_CONN__ |
| 26 | #define c3cn_conn_debug cxgb3i_log_info | 26 | #define c3cn_conn_debug cxgb3i_log_debug |
| 27 | #else | 27 | #else |
| 28 | #define c3cn_conn_debug(fmt...) | 28 | #define c3cn_conn_debug(fmt...) |
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #ifdef __DEBUG_C3CN_TX__ | 31 | #ifdef __DEBUG_C3CN_TX__ |
| 32 | #define c3cn_tx_debug cxgb3i_log_debug | 32 | #define c3cn_tx_debug cxgb3i_log_debug |
| 33 | #else | 33 | #else |
| 34 | #define c3cn_tx_debug(fmt...) | 34 | #define c3cn_tx_debug(fmt...) |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | #ifdef __DEBUG_C3CN_RX__ | 37 | #ifdef __DEBUG_C3CN_RX__ |
| 38 | #define c3cn_rx_debug cxgb3i_log_debug | 38 | #define c3cn_rx_debug cxgb3i_log_debug |
| 39 | #else | 39 | #else |
| 40 | #define c3cn_rx_debug(fmt...) | 40 | #define c3cn_rx_debug(fmt...) |
| 41 | #endif | 41 | #endif |
| @@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024; | |||
| 47 | module_param(cxgb3_rcv_win, int, 0644); | 47 | module_param(cxgb3_rcv_win, int, 0644); |
| 48 | MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); | 48 | MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); |
| 49 | 49 | ||
| 50 | static int cxgb3_snd_win = 64 * 1024; | 50 | static int cxgb3_snd_win = 128 * 1024; |
| 51 | module_param(cxgb3_snd_win, int, 0644); | 51 | module_param(cxgb3_snd_win, int, 0644); |
| 52 | MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)"); | 52 | MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)"); |
| 53 | 53 | ||
| 54 | static int cxgb3_rx_credit_thres = 10 * 1024; | 54 | static int cxgb3_rx_credit_thres = 10 * 1024; |
| 55 | module_param(cxgb3_rx_credit_thres, int, 0644); | 55 | module_param(cxgb3_rx_credit_thres, int, 0644); |
| @@ -301,8 +301,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) | |||
| 301 | static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, | 301 | static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, |
| 302 | int flags) | 302 | int flags) |
| 303 | { | 303 | { |
| 304 | CXGB3_SKB_CB(skb)->seq = c3cn->write_seq; | 304 | skb_tcp_seq(skb) = c3cn->write_seq; |
| 305 | CXGB3_SKB_CB(skb)->flags = flags; | 305 | skb_flags(skb) = flags; |
| 306 | __skb_queue_tail(&c3cn->write_queue, skb); | 306 | __skb_queue_tail(&c3cn->write_queue, skb); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| @@ -457,12 +457,9 @@ static unsigned int wrlen __read_mostly; | |||
| 457 | * The number of WRs needed for an skb depends on the number of fragments | 457 | * The number of WRs needed for an skb depends on the number of fragments |
| 458 | * in the skb and whether it has any payload in its main body. This maps the | 458 | * in the skb and whether it has any payload in its main body. This maps the |
| 459 | * length of the gather list represented by an skb into the # of necessary WRs. | 459 | * length of the gather list represented by an skb into the # of necessary WRs. |
| 460 | * | 460 | * The extra two fragments are for iscsi bhs and payload padding. |
| 461 | * The max. length of an skb is controlled by the max pdu size which is ~16K. | ||
| 462 | * Also, assume the min. fragment length is the sector size (512), then add | ||
| 463 | * extra fragment counts for iscsi bhs and payload padding. | ||
| 464 | */ | 461 | */ |
| 465 | #define SKB_WR_LIST_SIZE (16384/512 + 3) | 462 | #define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2) |
| 466 | static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; | 463 | static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; |
| 467 | 464 | ||
| 468 | static void s3_init_wr_tab(unsigned int wr_len) | 465 | static void s3_init_wr_tab(unsigned int wr_len) |
| @@ -485,7 +482,7 @@ static void s3_init_wr_tab(unsigned int wr_len) | |||
| 485 | 482 | ||
| 486 | static inline void reset_wr_list(struct s3_conn *c3cn) | 483 | static inline void reset_wr_list(struct s3_conn *c3cn) |
| 487 | { | 484 | { |
| 488 | c3cn->wr_pending_head = NULL; | 485 | c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL; |
| 489 | } | 486 | } |
| 490 | 487 | ||
| 491 | /* | 488 | /* |
| @@ -496,7 +493,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn) | |||
| 496 | static inline void enqueue_wr(struct s3_conn *c3cn, | 493 | static inline void enqueue_wr(struct s3_conn *c3cn, |
| 497 | struct sk_buff *skb) | 494 | struct sk_buff *skb) |
| 498 | { | 495 | { |
| 499 | skb_wr_data(skb) = NULL; | 496 | skb_tx_wr_next(skb) = NULL; |
| 500 | 497 | ||
| 501 | /* | 498 | /* |
| 502 | * We want to take an extra reference since both us and the driver | 499 | * We want to take an extra reference since both us and the driver |
| @@ -509,10 +506,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn, | |||
| 509 | if (!c3cn->wr_pending_head) | 506 | if (!c3cn->wr_pending_head) |
| 510 | c3cn->wr_pending_head = skb; | 507 | c3cn->wr_pending_head = skb; |
| 511 | else | 508 | else |
| 512 | skb_wr_data(skb) = skb; | 509 | skb_tx_wr_next(c3cn->wr_pending_tail) = skb; |
| 513 | c3cn->wr_pending_tail = skb; | 510 | c3cn->wr_pending_tail = skb; |
| 514 | } | 511 | } |
| 515 | 512 | ||
| 513 | static int count_pending_wrs(struct s3_conn *c3cn) | ||
| 514 | { | ||
| 515 | int n = 0; | ||
| 516 | const struct sk_buff *skb = c3cn->wr_pending_head; | ||
| 517 | |||
| 518 | while (skb) { | ||
| 519 | n += skb->csum; | ||
| 520 | skb = skb_tx_wr_next(skb); | ||
| 521 | } | ||
| 522 | return n; | ||
| 523 | } | ||
| 524 | |||
| 516 | static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) | 525 | static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) |
| 517 | { | 526 | { |
| 518 | return c3cn->wr_pending_head; | 527 | return c3cn->wr_pending_head; |
| @@ -529,8 +538,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn) | |||
| 529 | 538 | ||
| 530 | if (likely(skb)) { | 539 | if (likely(skb)) { |
| 531 | /* Don't bother clearing the tail */ | 540 | /* Don't bother clearing the tail */ |
| 532 | c3cn->wr_pending_head = skb_wr_data(skb); | 541 | c3cn->wr_pending_head = skb_tx_wr_next(skb); |
| 533 | skb_wr_data(skb) = NULL; | 542 | skb_tx_wr_next(skb) = NULL; |
| 534 | } | 543 | } |
| 535 | return skb; | 544 | return skb; |
| 536 | } | 545 | } |
| @@ -543,13 +552,14 @@ static void purge_wr_queue(struct s3_conn *c3cn) | |||
| 543 | } | 552 | } |
| 544 | 553 | ||
| 545 | static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, | 554 | static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, |
| 546 | int len) | 555 | int len, int req_completion) |
| 547 | { | 556 | { |
| 548 | struct tx_data_wr *req; | 557 | struct tx_data_wr *req; |
| 549 | 558 | ||
| 550 | skb_reset_transport_header(skb); | 559 | skb_reset_transport_header(skb); |
| 551 | req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); | 560 | req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); |
| 552 | req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)); | 561 | req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) | |
| 562 | (req_completion ? F_WR_COMPL : 0)); | ||
| 553 | req->wr_lo = htonl(V_WR_TID(c3cn->tid)); | 563 | req->wr_lo = htonl(V_WR_TID(c3cn->tid)); |
| 554 | req->sndseq = htonl(c3cn->snd_nxt); | 564 | req->sndseq = htonl(c3cn->snd_nxt); |
| 555 | /* len includes the length of any HW ULP additions */ | 565 | /* len includes the length of any HW ULP additions */ |
| @@ -592,7 +602,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 592 | 602 | ||
| 593 | if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || | 603 | if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || |
| 594 | c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || | 604 | c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || |
| 595 | c3cn->state == C3CN_STATE_ABORTING)) { | 605 | c3cn->state >= C3CN_STATE_ABORTING)) { |
| 596 | c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", | 606 | c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", |
| 597 | c3cn, c3cn->state); | 607 | c3cn, c3cn->state); |
| 598 | return 0; | 608 | return 0; |
| @@ -615,7 +625,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 615 | if (c3cn->wr_avail < wrs_needed) { | 625 | if (c3cn->wr_avail < wrs_needed) { |
| 616 | c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " | 626 | c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " |
| 617 | "wr %d < %u.\n", | 627 | "wr %d < %u.\n", |
| 618 | c3cn, skb->len, skb->datalen, frags, | 628 | c3cn, skb->len, skb->data_len, frags, |
| 619 | wrs_needed, c3cn->wr_avail); | 629 | wrs_needed, c3cn->wr_avail); |
| 620 | break; | 630 | break; |
| 621 | } | 631 | } |
| @@ -627,20 +637,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 627 | c3cn->wr_unacked += wrs_needed; | 637 | c3cn->wr_unacked += wrs_needed; |
| 628 | enqueue_wr(c3cn, skb); | 638 | enqueue_wr(c3cn, skb); |
| 629 | 639 | ||
| 630 | if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) { | 640 | c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, " |
| 631 | len += ulp_extra_len(skb); | 641 | "wr %d, left %u, unack %u.\n", |
| 632 | make_tx_data_wr(c3cn, skb, len); | 642 | c3cn, skb->len, skb->data_len, frags, |
| 633 | c3cn->snd_nxt += len; | 643 | wrs_needed, c3cn->wr_avail, c3cn->wr_unacked); |
| 634 | if ((req_completion | 644 | |
| 635 | && c3cn->wr_unacked == wrs_needed) | ||
| 636 | || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL) | ||
| 637 | || c3cn->wr_unacked >= c3cn->wr_max / 2) { | ||
| 638 | struct work_request_hdr *wr = cplhdr(skb); | ||
| 639 | 645 | ||
| 640 | wr->wr_hi |= htonl(F_WR_COMPL); | 646 | if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) { |
| 647 | if ((req_completion && | ||
| 648 | c3cn->wr_unacked == wrs_needed) || | ||
| 649 | (skb_flags(skb) & C3CB_FLAG_COMPL) || | ||
| 650 | c3cn->wr_unacked >= c3cn->wr_max / 2) { | ||
| 651 | req_completion = 1; | ||
| 641 | c3cn->wr_unacked = 0; | 652 | c3cn->wr_unacked = 0; |
| 642 | } | 653 | } |
| 643 | CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR; | 654 | len += ulp_extra_len(skb); |
| 655 | make_tx_data_wr(c3cn, skb, len, req_completion); | ||
| 656 | c3cn->snd_nxt += len; | ||
| 657 | skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR; | ||
| 644 | } | 658 | } |
| 645 | 659 | ||
| 646 | total_size += skb->truesize; | 660 | total_size += skb->truesize; |
| @@ -735,8 +749,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 735 | if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) | 749 | if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) |
| 736 | /* upper layer has requested closing */ | 750 | /* upper layer has requested closing */ |
| 737 | send_abort_req(c3cn); | 751 | send_abort_req(c3cn); |
| 738 | else if (c3cn_push_tx_frames(c3cn, 1)) | 752 | else { |
| 753 | if (skb_queue_len(&c3cn->write_queue)) | ||
| 754 | c3cn_push_tx_frames(c3cn, 1); | ||
| 739 | cxgb3i_conn_tx_open(c3cn); | 755 | cxgb3i_conn_tx_open(c3cn); |
| 756 | } | ||
| 740 | } | 757 | } |
| 741 | 758 | ||
| 742 | static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, | 759 | static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, |
| @@ -1082,8 +1099,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1082 | return; | 1099 | return; |
| 1083 | } | 1100 | } |
| 1084 | 1101 | ||
| 1085 | CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq); | 1102 | skb_tcp_seq(skb) = ntohl(hdr_cpl->seq); |
| 1086 | CXGB3_SKB_CB(skb)->flags = 0; | 1103 | skb_flags(skb) = 0; |
| 1087 | 1104 | ||
| 1088 | skb_reset_transport_header(skb); | 1105 | skb_reset_transport_header(skb); |
| 1089 | __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); | 1106 | __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); |
| @@ -1103,12 +1120,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1103 | goto abort_conn; | 1120 | goto abort_conn; |
| 1104 | 1121 | ||
| 1105 | skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; | 1122 | skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; |
| 1106 | skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len); | 1123 | skb_rx_pdulen(skb) = ntohs(ddp_cpl.len); |
| 1107 | skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); | 1124 | skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); |
| 1108 | status = ntohl(ddp_cpl.ddp_status); | 1125 | status = ntohl(ddp_cpl.ddp_status); |
| 1109 | 1126 | ||
| 1110 | c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", | 1127 | c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", |
| 1111 | skb, skb->len, skb_ulp_pdulen(skb), status); | 1128 | skb, skb->len, skb_rx_pdulen(skb), status); |
| 1112 | 1129 | ||
| 1113 | if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) | 1130 | if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) |
| 1114 | skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; | 1131 | skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; |
| @@ -1126,7 +1143,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1126 | } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) | 1143 | } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) |
| 1127 | skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; | 1144 | skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; |
| 1128 | 1145 | ||
| 1129 | c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb); | 1146 | c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb); |
| 1130 | __pskb_trim(skb, len); | 1147 | __pskb_trim(skb, len); |
| 1131 | __skb_queue_tail(&c3cn->receive_queue, skb); | 1148 | __skb_queue_tail(&c3cn->receive_queue, skb); |
| 1132 | cxgb3i_conn_pdu_ready(c3cn); | 1149 | cxgb3i_conn_pdu_ready(c3cn); |
| @@ -1151,12 +1168,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx) | |||
| 1151 | * Process an acknowledgment of WR completion. Advance snd_una and send the | 1168 | * Process an acknowledgment of WR completion. Advance snd_una and send the |
| 1152 | * next batch of work requests from the write queue. | 1169 | * next batch of work requests from the write queue. |
| 1153 | */ | 1170 | */ |
| 1171 | static void check_wr_invariants(struct s3_conn *c3cn) | ||
| 1172 | { | ||
| 1173 | int pending = count_pending_wrs(c3cn); | ||
| 1174 | |||
| 1175 | if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max)) | ||
| 1176 | cxgb3i_log_error("TID %u: credit imbalance: avail %u, " | ||
| 1177 | "pending %u, total should be %u\n", | ||
| 1178 | c3cn->tid, c3cn->wr_avail, pending, | ||
| 1179 | c3cn->wr_max); | ||
| 1180 | } | ||
| 1181 | |||
| 1154 | static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | 1182 | static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) |
| 1155 | { | 1183 | { |
| 1156 | struct cpl_wr_ack *hdr = cplhdr(skb); | 1184 | struct cpl_wr_ack *hdr = cplhdr(skb); |
| 1157 | unsigned int credits = ntohs(hdr->credits); | 1185 | unsigned int credits = ntohs(hdr->credits); |
| 1158 | u32 snd_una = ntohl(hdr->snd_una); | 1186 | u32 snd_una = ntohl(hdr->snd_una); |
| 1159 | 1187 | ||
| 1188 | c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n", | ||
| 1189 | credits, c3cn->wr_avail, c3cn->wr_unacked, | ||
| 1190 | c3cn->tid, c3cn->state); | ||
| 1191 | |||
| 1160 | c3cn->wr_avail += credits; | 1192 | c3cn->wr_avail += credits; |
| 1161 | if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) | 1193 | if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) |
| 1162 | c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; | 1194 | c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; |
| @@ -1171,6 +1203,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1171 | break; | 1203 | break; |
| 1172 | } | 1204 | } |
| 1173 | if (unlikely(credits < p->csum)) { | 1205 | if (unlikely(credits < p->csum)) { |
| 1206 | struct tx_data_wr *w = cplhdr(p); | ||
| 1207 | cxgb3i_log_error("TID %u got %u WR credits need %u, " | ||
| 1208 | "len %u, main body %u, frags %u, " | ||
| 1209 | "seq # %u, ACK una %u, ACK nxt %u, " | ||
| 1210 | "WR_AVAIL %u, WRs pending %u\n", | ||
| 1211 | c3cn->tid, credits, p->csum, p->len, | ||
| 1212 | p->len - p->data_len, | ||
| 1213 | skb_shinfo(p)->nr_frags, | ||
| 1214 | ntohl(w->sndseq), snd_una, | ||
| 1215 | ntohl(hdr->snd_nxt), c3cn->wr_avail, | ||
| 1216 | count_pending_wrs(c3cn) - credits); | ||
| 1174 | p->csum -= credits; | 1217 | p->csum -= credits; |
| 1175 | break; | 1218 | break; |
| 1176 | } else { | 1219 | } else { |
| @@ -1180,15 +1223,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1180 | } | 1223 | } |
| 1181 | } | 1224 | } |
| 1182 | 1225 | ||
| 1183 | if (unlikely(before(snd_una, c3cn->snd_una))) | 1226 | check_wr_invariants(c3cn); |
| 1227 | |||
| 1228 | if (unlikely(before(snd_una, c3cn->snd_una))) { | ||
| 1229 | cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK " | ||
| 1230 | "snd_una %u\n", | ||
| 1231 | c3cn->tid, snd_una, c3cn->snd_una); | ||
| 1184 | goto out_free; | 1232 | goto out_free; |
| 1233 | } | ||
| 1185 | 1234 | ||
| 1186 | if (c3cn->snd_una != snd_una) { | 1235 | if (c3cn->snd_una != snd_una) { |
| 1187 | c3cn->snd_una = snd_una; | 1236 | c3cn->snd_una = snd_una; |
| 1188 | dst_confirm(c3cn->dst_cache); | 1237 | dst_confirm(c3cn->dst_cache); |
| 1189 | } | 1238 | } |
| 1190 | 1239 | ||
| 1191 | if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0)) | 1240 | if (skb_queue_len(&c3cn->write_queue)) { |
| 1241 | if (c3cn_push_tx_frames(c3cn, 0)) | ||
| 1242 | cxgb3i_conn_tx_open(c3cn); | ||
| 1243 | } else | ||
| 1192 | cxgb3i_conn_tx_open(c3cn); | 1244 | cxgb3i_conn_tx_open(c3cn); |
| 1193 | out_free: | 1245 | out_free: |
| 1194 | __kfree_skb(skb); | 1246 | __kfree_skb(skb); |
| @@ -1452,7 +1504,7 @@ static void init_offload_conn(struct s3_conn *c3cn, | |||
| 1452 | struct dst_entry *dst) | 1504 | struct dst_entry *dst) |
| 1453 | { | 1505 | { |
| 1454 | BUG_ON(c3cn->cdev != cdev); | 1506 | BUG_ON(c3cn->cdev != cdev); |
| 1455 | c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs; | 1507 | c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1; |
| 1456 | c3cn->wr_unacked = 0; | 1508 | c3cn->wr_unacked = 0; |
| 1457 | c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); | 1509 | c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); |
| 1458 | 1510 | ||
| @@ -1671,9 +1723,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1671 | goto out_err; | 1723 | goto out_err; |
| 1672 | } | 1724 | } |
| 1673 | 1725 | ||
| 1674 | err = -EPIPE; | ||
| 1675 | if (c3cn->err) { | 1726 | if (c3cn->err) { |
| 1676 | c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); | 1727 | c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); |
| 1728 | err = -EPIPE; | ||
| 1729 | goto out_err; | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) { | ||
| 1733 | c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n", | ||
| 1734 | c3cn, c3cn->write_seq, c3cn->snd_una, | ||
| 1735 | cxgb3_snd_win); | ||
| 1736 | err = -EAGAIN; | ||
| 1677 | goto out_err; | 1737 | goto out_err; |
| 1678 | } | 1738 | } |
| 1679 | 1739 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index d23156907ff..6344b9eb258 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h | |||
| @@ -178,25 +178,33 @@ void cxgb3i_c3cn_release(struct s3_conn *); | |||
| 178 | * @flag: see C3CB_FLAG_* below | 178 | * @flag: see C3CB_FLAG_* below |
| 179 | * @ulp_mode: ULP mode/submode of sk_buff | 179 | * @ulp_mode: ULP mode/submode of sk_buff |
| 180 | * @seq: tcp sequence number | 180 | * @seq: tcp sequence number |
| 181 | * @ddigest: pdu data digest | ||
| 182 | * @pdulen: recovered pdu length | ||
| 183 | * @wr_data: scratch area for tx wr | ||
| 184 | */ | 181 | */ |
| 182 | struct cxgb3_skb_rx_cb { | ||
| 183 | __u32 ddigest; /* data digest */ | ||
| 184 | __u32 pdulen; /* recovered pdu length */ | ||
| 185 | }; | ||
| 186 | |||
| 187 | struct cxgb3_skb_tx_cb { | ||
| 188 | struct sk_buff *wr_next; /* next wr */ | ||
| 189 | }; | ||
| 190 | |||
| 185 | struct cxgb3_skb_cb { | 191 | struct cxgb3_skb_cb { |
| 186 | __u8 flags; | 192 | __u8 flags; |
| 187 | __u8 ulp_mode; | 193 | __u8 ulp_mode; |
| 188 | __u32 seq; | 194 | __u32 seq; |
| 189 | __u32 ddigest; | 195 | union { |
| 190 | __u32 pdulen; | 196 | struct cxgb3_skb_rx_cb rx; |
| 191 | struct sk_buff *wr_data; | 197 | struct cxgb3_skb_tx_cb tx; |
| 198 | }; | ||
| 192 | }; | 199 | }; |
| 193 | 200 | ||
| 194 | #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) | 201 | #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) |
| 195 | 202 | #define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags) | |
| 196 | #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) | 203 | #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) |
| 197 | #define skb_ulp_ddigest(skb) (CXGB3_SKB_CB(skb)->ddigest) | 204 | #define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq) |
| 198 | #define skb_ulp_pdulen(skb) (CXGB3_SKB_CB(skb)->pdulen) | 205 | #define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest) |
| 199 | #define skb_wr_data(skb) (CXGB3_SKB_CB(skb)->wr_data) | 206 | #define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen) |
| 207 | #define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next) | ||
| 200 | 208 | ||
| 201 | enum c3cb_flags { | 209 | enum c3cb_flags { |
| 202 | C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ | 210 | C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ |
| @@ -217,6 +225,7 @@ struct sge_opaque_hdr { | |||
| 217 | /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ | 225 | /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ |
| 218 | #define TX_HEADER_LEN \ | 226 | #define TX_HEADER_LEN \ |
| 219 | (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) | 227 | (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) |
| 228 | #define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN) | ||
| 220 | 229 | ||
| 221 | /* | 230 | /* |
| 222 | * get and set private ip for iscsi traffic | 231 | * get and set private ip for iscsi traffic |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index ce7ce8c6094..17115c230d6 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c | |||
| @@ -32,6 +32,10 @@ | |||
| 32 | #define cxgb3i_tx_debug(fmt...) | 32 | #define cxgb3i_tx_debug(fmt...) |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | /* always allocate rooms for AHS */ | ||
| 36 | #define SKB_TX_PDU_HEADER_LEN \ | ||
| 37 | (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE) | ||
| 38 | static unsigned int skb_extra_headroom; | ||
| 35 | static struct page *pad_page; | 39 | static struct page *pad_page; |
| 36 | 40 | ||
| 37 | /* | 41 | /* |
| @@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) | |||
| 146 | 150 | ||
| 147 | void cxgb3i_conn_cleanup_task(struct iscsi_task *task) | 151 | void cxgb3i_conn_cleanup_task(struct iscsi_task *task) |
| 148 | { | 152 | { |
| 149 | struct iscsi_tcp_task *tcp_task = task->dd_data; | 153 | struct cxgb3i_task_data *tdata = task->dd_data + |
| 154 | sizeof(struct iscsi_tcp_task); | ||
| 150 | 155 | ||
| 151 | /* never reached the xmit task callout */ | 156 | /* never reached the xmit task callout */ |
| 152 | if (tcp_task->dd_data) | 157 | if (tdata->skb) |
| 153 | kfree_skb(tcp_task->dd_data); | 158 | __kfree_skb(tdata->skb); |
| 154 | tcp_task->dd_data = NULL; | 159 | memset(tdata, 0, sizeof(struct cxgb3i_task_data)); |
| 155 | 160 | ||
| 156 | /* MNC - Do we need a check in case this is called but | 161 | /* MNC - Do we need a check in case this is called but |
| 157 | * cxgb3i_conn_alloc_pdu has never been called on the task */ | 162 | * cxgb3i_conn_alloc_pdu has never been called on the task */ |
| @@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task) | |||
| 159 | iscsi_tcp_cleanup_task(task); | 164 | iscsi_tcp_cleanup_task(task); |
| 160 | } | 165 | } |
| 161 | 166 | ||
| 162 | /* | 167 | static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, |
| 163 | * We do not support ahs yet | 168 | unsigned int offset, unsigned int *off, |
| 164 | */ | 169 | struct scatterlist **sgp) |
| 170 | { | ||
| 171 | int i; | ||
| 172 | struct scatterlist *sg; | ||
| 173 | |||
| 174 | for_each_sg(sgl, sg, sgcnt, i) { | ||
| 175 | if (offset < sg->length) { | ||
| 176 | *off = offset; | ||
| 177 | *sgp = sg; | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | offset -= sg->length; | ||
| 181 | } | ||
| 182 | return -EFAULT; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, | ||
| 186 | unsigned int dlen, skb_frag_t *frags, | ||
| 187 | int frag_max) | ||
| 188 | { | ||
| 189 | unsigned int datalen = dlen; | ||
| 190 | unsigned int sglen = sg->length - sgoffset; | ||
| 191 | struct page *page = sg_page(sg); | ||
| 192 | int i; | ||
| 193 | |||
| 194 | i = 0; | ||
| 195 | do { | ||
| 196 | unsigned int copy; | ||
| 197 | |||
| 198 | if (!sglen) { | ||
| 199 | sg = sg_next(sg); | ||
| 200 | if (!sg) { | ||
| 201 | cxgb3i_log_error("%s, sg NULL, len %u/%u.\n", | ||
| 202 | __func__, datalen, dlen); | ||
| 203 | return -EINVAL; | ||
| 204 | } | ||
| 205 | sgoffset = 0; | ||
| 206 | sglen = sg->length; | ||
| 207 | page = sg_page(sg); | ||
| 208 | |||
| 209 | } | ||
| 210 | copy = min(datalen, sglen); | ||
| 211 | if (i && page == frags[i - 1].page && | ||
| 212 | sgoffset + sg->offset == | ||
| 213 | frags[i - 1].page_offset + frags[i - 1].size) { | ||
| 214 | frags[i - 1].size += copy; | ||
| 215 | } else { | ||
| 216 | if (i >= frag_max) { | ||
| 217 | cxgb3i_log_error("%s, too many pages %u, " | ||
| 218 | "dlen %u.\n", __func__, | ||
| 219 | frag_max, dlen); | ||
| 220 | return -EINVAL; | ||
| 221 | } | ||
| 222 | |||
| 223 | frags[i].page = page; | ||
| 224 | frags[i].page_offset = sg->offset + sgoffset; | ||
| 225 | frags[i].size = copy; | ||
| 226 | i++; | ||
| 227 | } | ||
| 228 | datalen -= copy; | ||
| 229 | sgoffset += copy; | ||
| 230 | sglen -= copy; | ||
| 231 | } while (datalen); | ||
| 232 | |||
| 233 | return i; | ||
| 234 | } | ||
| 235 | |||
| 165 | int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) | 236 | int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) |
| 166 | { | 237 | { |
| 238 | struct iscsi_conn *conn = task->conn; | ||
| 167 | struct iscsi_tcp_task *tcp_task = task->dd_data; | 239 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
| 168 | struct sk_buff *skb; | 240 | struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task); |
| 241 | struct scsi_cmnd *sc = task->sc; | ||
| 242 | int headroom = SKB_TX_PDU_HEADER_LEN; | ||
| 169 | 243 | ||
| 244 | tcp_task->dd_data = tdata; | ||
| 170 | task->hdr = NULL; | 245 | task->hdr = NULL; |
| 171 | /* always allocate rooms for AHS */ | 246 | |
| 172 | skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + | 247 | /* write command, need to send data pdus */ |
| 173 | TX_HEADER_LEN, GFP_ATOMIC); | 248 | if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT || |
| 174 | if (!skb) | 249 | (opcode == ISCSI_OP_SCSI_CMD && |
| 250 | (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE)))) | ||
| 251 | headroom += min(skb_extra_headroom, conn->max_xmit_dlength); | ||
| 252 | |||
| 253 | tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC); | ||
| 254 | if (!tdata->skb) | ||
| 175 | return -ENOMEM; | 255 | return -ENOMEM; |
| 256 | skb_reserve(tdata->skb, TX_HEADER_LEN); | ||
| 176 | 257 | ||
| 177 | cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", | 258 | cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", |
| 178 | task, opcode, skb); | 259 | task, opcode, tdata->skb); |
| 179 | 260 | ||
| 180 | tcp_task->dd_data = skb; | 261 | task->hdr = (struct iscsi_hdr *)tdata->skb->data; |
| 181 | skb_reserve(skb, TX_HEADER_LEN); | 262 | task->hdr_max = SKB_TX_PDU_HEADER_LEN; |
| 182 | task->hdr = (struct iscsi_hdr *)skb->data; | ||
| 183 | task->hdr_max = sizeof(struct iscsi_hdr); | ||
| 184 | 263 | ||
| 185 | /* data_out uses scsi_cmd's itt */ | 264 | /* data_out uses scsi_cmd's itt */ |
| 186 | if (opcode != ISCSI_OP_SCSI_DATA_OUT) | 265 | if (opcode != ISCSI_OP_SCSI_DATA_OUT) |
| @@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) | |||
| 192 | int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, | 271 | int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, |
| 193 | unsigned int count) | 272 | unsigned int count) |
| 194 | { | 273 | { |
| 195 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 196 | struct sk_buff *skb = tcp_task->dd_data; | ||
| 197 | struct iscsi_conn *conn = task->conn; | 274 | struct iscsi_conn *conn = task->conn; |
| 198 | struct page *pg; | 275 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
| 276 | struct cxgb3i_task_data *tdata = tcp_task->dd_data; | ||
| 277 | struct sk_buff *skb = tdata->skb; | ||
| 199 | unsigned int datalen = count; | 278 | unsigned int datalen = count; |
| 200 | int i, padlen = iscsi_padding(count); | 279 | int i, padlen = iscsi_padding(count); |
| 201 | skb_frag_t *frag; | 280 | struct page *pg; |
| 202 | 281 | ||
| 203 | cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", | 282 | cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", |
| 204 | task, task->sc, offset, count, skb); | 283 | task, task->sc, offset, count, skb); |
| @@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, | |||
| 209 | return 0; | 288 | return 0; |
| 210 | 289 | ||
| 211 | if (task->sc) { | 290 | if (task->sc) { |
| 212 | struct scatterlist *sg; | 291 | struct scsi_data_buffer *sdb = scsi_out(task->sc); |
| 213 | struct scsi_data_buffer *sdb; | 292 | struct scatterlist *sg = NULL; |
| 214 | unsigned int sgoffset = offset; | 293 | int err; |
| 215 | struct page *sgpg; | 294 | |
| 216 | unsigned int sglen; | 295 | tdata->offset = offset; |
| 217 | 296 | tdata->count = count; | |
| 218 | sdb = scsi_out(task->sc); | 297 | err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents, |
| 219 | sg = sdb->table.sgl; | 298 | tdata->offset, &tdata->sgoffset, &sg); |
| 220 | 299 | if (err < 0) { | |
| 221 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { | 300 | cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n", |
| 222 | cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n", | 301 | sdb->table.nents, tdata->offset, |
| 223 | i, sg_page(sg), sg->length, sg->offset); | 302 | sdb->length); |
| 224 | 303 | return err; | |
| 225 | if (sgoffset < sg->length) | ||
| 226 | break; | ||
| 227 | sgoffset -= sg->length; | ||
| 228 | } | 304 | } |
| 229 | sgpg = sg_page(sg); | 305 | err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count, |
| 230 | sglen = sg->length - sgoffset; | 306 | tdata->frags, MAX_PDU_FRAGS); |
| 231 | 307 | if (err < 0) { | |
| 232 | do { | 308 | cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n", |
| 233 | int j = skb_shinfo(skb)->nr_frags; | 309 | sdb->table.nents, tdata->offset, |
| 234 | unsigned int copy; | 310 | tdata->count); |
| 235 | 311 | return err; | |
| 236 | if (!sglen) { | 312 | } |
| 237 | sg = sg_next(sg); | 313 | tdata->nr_frags = err; |
| 238 | sgpg = sg_page(sg); | 314 | |
| 239 | sgoffset = 0; | 315 | if (tdata->nr_frags > MAX_SKB_FRAGS || |
| 240 | sglen = sg->length; | 316 | (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { |
| 241 | ++i; | 317 | char *dst = skb->data + task->hdr_len; |
| 318 | skb_frag_t *frag = tdata->frags; | ||
| 319 | |||
| 320 | /* data fits in the skb's headroom */ | ||
| 321 | for (i = 0; i < tdata->nr_frags; i++, frag++) { | ||
| 322 | char *src = kmap_atomic(frag->page, | ||
| 323 | KM_SOFTIRQ0); | ||
| 324 | |||
| 325 | memcpy(dst, src+frag->page_offset, frag->size); | ||
| 326 | dst += frag->size; | ||
| 327 | kunmap_atomic(src, KM_SOFTIRQ0); | ||
| 242 | } | 328 | } |
| 243 | copy = min(sglen, datalen); | 329 | if (padlen) { |
| 244 | if (j && skb_can_coalesce(skb, j, sgpg, | 330 | memset(dst, 0, padlen); |
| 245 | sg->offset + sgoffset)) { | 331 | padlen = 0; |
| 246 | skb_shinfo(skb)->frags[j - 1].size += copy; | ||
| 247 | } else { | ||
| 248 | get_page(sgpg); | ||
| 249 | skb_fill_page_desc(skb, j, sgpg, | ||
| 250 | sg->offset + sgoffset, copy); | ||
| 251 | } | 332 | } |
| 252 | sgoffset += copy; | 333 | skb_put(skb, count + padlen); |
| 253 | sglen -= copy; | 334 | } else { |
| 254 | datalen -= copy; | 335 | /* data fit into frag_list */ |
| 255 | } while (datalen); | 336 | for (i = 0; i < tdata->nr_frags; i++) |
| 337 | get_page(tdata->frags[i].page); | ||
| 338 | |||
| 339 | memcpy(skb_shinfo(skb)->frags, tdata->frags, | ||
| 340 | sizeof(skb_frag_t) * tdata->nr_frags); | ||
| 341 | skb_shinfo(skb)->nr_frags = tdata->nr_frags; | ||
| 342 | skb->len += count; | ||
| 343 | skb->data_len += count; | ||
| 344 | skb->truesize += count; | ||
| 345 | } | ||
| 346 | |||
| 256 | } else { | 347 | } else { |
| 257 | pg = virt_to_page(task->data); | 348 | pg = virt_to_page(task->data); |
| 258 | 349 | ||
| 259 | while (datalen) { | 350 | get_page(pg); |
| 260 | i = skb_shinfo(skb)->nr_frags; | 351 | skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data), |
| 261 | frag = &skb_shinfo(skb)->frags[i]; | 352 | count); |
| 262 | 353 | skb->len += count; | |
| 263 | get_page(pg); | 354 | skb->data_len += count; |
| 264 | frag->page = pg; | 355 | skb->truesize += count; |
| 265 | frag->page_offset = 0; | ||
| 266 | frag->size = min((unsigned int)PAGE_SIZE, datalen); | ||
| 267 | |||
| 268 | skb_shinfo(skb)->nr_frags++; | ||
| 269 | datalen -= frag->size; | ||
| 270 | pg++; | ||
| 271 | } | ||
| 272 | } | 356 | } |
| 273 | 357 | ||
| 274 | if (padlen) { | 358 | if (padlen) { |
| 275 | i = skb_shinfo(skb)->nr_frags; | 359 | i = skb_shinfo(skb)->nr_frags; |
| 276 | frag = &skb_shinfo(skb)->frags[i]; | 360 | get_page(pad_page); |
| 277 | frag->page = pad_page; | 361 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0, |
| 278 | frag->page_offset = 0; | 362 | padlen); |
| 279 | frag->size = padlen; | 363 | |
| 280 | skb_shinfo(skb)->nr_frags++; | 364 | skb->data_len += padlen; |
| 365 | skb->truesize += padlen; | ||
| 366 | skb->len += padlen; | ||
| 281 | } | 367 | } |
| 282 | 368 | ||
| 283 | datalen = count + padlen; | ||
| 284 | skb->data_len += datalen; | ||
| 285 | skb->truesize += datalen; | ||
| 286 | skb->len += datalen; | ||
| 287 | return 0; | 369 | return 0; |
| 288 | } | 370 | } |
| 289 | 371 | ||
| 290 | int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | 372 | int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) |
| 291 | { | 373 | { |
| 292 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 293 | struct sk_buff *skb = tcp_task->dd_data; | ||
| 294 | struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; | 374 | struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; |
| 295 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 375 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 376 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 377 | struct cxgb3i_task_data *tdata = tcp_task->dd_data; | ||
| 378 | struct sk_buff *skb = tdata->skb; | ||
| 296 | unsigned int datalen; | 379 | unsigned int datalen; |
| 297 | int err; | 380 | int err; |
| 298 | 381 | ||
| @@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | |||
| 300 | return 0; | 383 | return 0; |
| 301 | 384 | ||
| 302 | datalen = skb->data_len; | 385 | datalen = skb->data_len; |
| 303 | tcp_task->dd_data = NULL; | 386 | tdata->skb = NULL; |
| 304 | err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); | 387 | err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); |
| 305 | cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", | ||
| 306 | task, skb, skb->len, skb->data_len, err); | ||
| 307 | if (err > 0) { | 388 | if (err > 0) { |
| 308 | int pdulen = err; | 389 | int pdulen = err; |
| 309 | 390 | ||
| 391 | cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", | ||
| 392 | task, skb, skb->len, skb->data_len, err); | ||
| 393 | |||
| 310 | if (task->conn->hdrdgst_en) | 394 | if (task->conn->hdrdgst_en) |
| 311 | pdulen += ISCSI_DIGEST_SIZE; | 395 | pdulen += ISCSI_DIGEST_SIZE; |
| 312 | if (datalen && task->conn->datadgst_en) | 396 | if (datalen && task->conn->datadgst_en) |
| @@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | |||
| 325 | return err; | 409 | return err; |
| 326 | } | 410 | } |
| 327 | /* reset skb to send when we are called again */ | 411 | /* reset skb to send when we are called again */ |
| 328 | tcp_task->dd_data = skb; | 412 | tdata->skb = skb; |
| 329 | return -EAGAIN; | 413 | return -EAGAIN; |
| 330 | } | 414 | } |
| 331 | 415 | ||
| 332 | int cxgb3i_pdu_init(void) | 416 | int cxgb3i_pdu_init(void) |
| 333 | { | 417 | { |
| 418 | if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS)) | ||
| 419 | skb_extra_headroom = SKB_TX_HEADROOM; | ||
| 334 | pad_page = alloc_page(GFP_KERNEL); | 420 | pad_page = alloc_page(GFP_KERNEL); |
| 335 | if (!pad_page) | 421 | if (!pad_page) |
| 336 | return -ENOMEM; | 422 | return -ENOMEM; |
| @@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) | |||
| 366 | skb = skb_peek(&c3cn->receive_queue); | 452 | skb = skb_peek(&c3cn->receive_queue); |
| 367 | while (!err && skb) { | 453 | while (!err && skb) { |
| 368 | __skb_unlink(skb, &c3cn->receive_queue); | 454 | __skb_unlink(skb, &c3cn->receive_queue); |
| 369 | read += skb_ulp_pdulen(skb); | 455 | read += skb_rx_pdulen(skb); |
| 456 | cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n", | ||
| 457 | conn, c3cn, skb, skb_rx_pdulen(skb)); | ||
| 370 | err = cxgb3i_conn_read_pdu_skb(conn, skb); | 458 | err = cxgb3i_conn_read_pdu_skb(conn, skb); |
| 371 | __kfree_skb(skb); | 459 | __kfree_skb(skb); |
| 372 | skb = skb_peek(&c3cn->receive_queue); | 460 | skb = skb_peek(&c3cn->receive_queue); |
| @@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) | |||
| 377 | cxgb3i_c3cn_rx_credits(c3cn, read); | 465 | cxgb3i_c3cn_rx_credits(c3cn, read); |
| 378 | } | 466 | } |
| 379 | conn->rxdata_octets += read; | 467 | conn->rxdata_octets += read; |
| 468 | |||
| 469 | if (err) { | ||
| 470 | cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err); | ||
| 471 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
| 472 | } | ||
| 380 | } | 473 | } |
| 381 | 474 | ||
| 382 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn) | 475 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn) |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h index a3f685cc236..0770b23d90d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.h | |||
| @@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss { | |||
| 53 | #define ULP2_FLAG_DCRC_ERROR 0x20 | 53 | #define ULP2_FLAG_DCRC_ERROR 0x20 |
| 54 | #define ULP2_FLAG_PAD_ERROR 0x40 | 54 | #define ULP2_FLAG_PAD_ERROR 0x40 |
| 55 | 55 | ||
| 56 | void cxgb3i_conn_closing(struct s3_conn *); | 56 | void cxgb3i_conn_closing(struct s3_conn *c3cn); |
| 57 | void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); | 57 | void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); |
| 58 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn); | 58 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn); |
| 59 | #endif | 59 | #endif |
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a48e4990fe1..34be88d7afa 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
| @@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_table[] = { | |||
| 1251 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, | 1251 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1252 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, | 1252 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1253 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, | 1253 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1254 | { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1254 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, | 1255 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1255 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, | 1256 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1256 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, | 1257 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 940dc32ff0d..b82ffd90632 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1040,12 +1040,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 1040 | action = ACTION_FAIL; | 1040 | action = ACTION_FAIL; |
| 1041 | break; | 1041 | break; |
| 1042 | case ABORTED_COMMAND: | 1042 | case ABORTED_COMMAND: |
| 1043 | action = ACTION_FAIL; | ||
| 1043 | if (sshdr.asc == 0x10) { /* DIF */ | 1044 | if (sshdr.asc == 0x10) { /* DIF */ |
| 1044 | description = "Target Data Integrity Failure"; | 1045 | description = "Target Data Integrity Failure"; |
| 1045 | action = ACTION_FAIL; | ||
| 1046 | error = -EILSEQ; | 1046 | error = -EILSEQ; |
| 1047 | } else | 1047 | } |
| 1048 | action = ACTION_RETRY; | ||
| 1049 | break; | 1048 | break; |
| 1050 | case NOT_READY: | 1049 | case NOT_READY: |
| 1051 | /* If the device is in the process of becoming | 1050 | /* If the device is in the process of becoming |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d57566b8be0..55310dbc10a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev); | |||
| 107 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | 107 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); |
| 108 | static void sd_print_result(struct scsi_disk *, int); | 108 | static void sd_print_result(struct scsi_disk *, int); |
| 109 | 109 | ||
| 110 | static DEFINE_SPINLOCK(sd_index_lock); | ||
| 110 | static DEFINE_IDA(sd_index_ida); | 111 | static DEFINE_IDA(sd_index_ida); |
| 111 | 112 | ||
| 112 | /* This semaphore is used to mediate the 0->1 reference get in the | 113 | /* This semaphore is used to mediate the 0->1 reference get in the |
| @@ -1914,7 +1915,9 @@ static int sd_probe(struct device *dev) | |||
| 1914 | if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) | 1915 | if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) |
| 1915 | goto out_put; | 1916 | goto out_put; |
| 1916 | 1917 | ||
| 1918 | spin_lock(&sd_index_lock); | ||
| 1917 | error = ida_get_new(&sd_index_ida, &index); | 1919 | error = ida_get_new(&sd_index_ida, &index); |
| 1920 | spin_unlock(&sd_index_lock); | ||
| 1918 | } while (error == -EAGAIN); | 1921 | } while (error == -EAGAIN); |
| 1919 | 1922 | ||
| 1920 | if (error) | 1923 | if (error) |
| @@ -1936,7 +1939,9 @@ static int sd_probe(struct device *dev) | |||
| 1936 | return 0; | 1939 | return 0; |
| 1937 | 1940 | ||
| 1938 | out_free_index: | 1941 | out_free_index: |
| 1942 | spin_lock(&sd_index_lock); | ||
| 1939 | ida_remove(&sd_index_ida, index); | 1943 | ida_remove(&sd_index_ida, index); |
| 1944 | spin_unlock(&sd_index_lock); | ||
| 1940 | out_put: | 1945 | out_put: |
| 1941 | put_disk(gd); | 1946 | put_disk(gd); |
| 1942 | out_free: | 1947 | out_free: |
| @@ -1986,7 +1991,9 @@ static void scsi_disk_release(struct device *dev) | |||
| 1986 | struct scsi_disk *sdkp = to_scsi_disk(dev); | 1991 | struct scsi_disk *sdkp = to_scsi_disk(dev); |
| 1987 | struct gendisk *disk = sdkp->disk; | 1992 | struct gendisk *disk = sdkp->disk; |
| 1988 | 1993 | ||
| 1994 | spin_lock(&sd_index_lock); | ||
| 1989 | ida_remove(&sd_index_ida, sdkp->index); | 1995 | ida_remove(&sd_index_ida, sdkp->index); |
| 1996 | spin_unlock(&sd_index_lock); | ||
| 1990 | 1997 | ||
| 1991 | disk->private_data = NULL; | 1998 | disk->private_data = NULL; |
| 1992 | put_disk(disk); | 1999 | put_disk(disk); |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b976..022e89ffec1 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
| @@ -133,7 +133,7 @@ | |||
| 133 | # define SCSPTR3 0xffed0024 /* 16 bit SCIF */ | 133 | # define SCSPTR3 0xffed0024 /* 16 bit SCIF */ |
| 134 | # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ | 134 | # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ |
| 135 | # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ | 135 | # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ |
| 136 | # define SCIF_OPER 0x0001 /* Overrun error bit */ | 136 | # define SCIF_ORER 0x0001 /* Overrun error bit */ |
| 137 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 137 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
| 138 | #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ | 138 | #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ |
| 139 | defined(CONFIG_CPU_SUBTYPE_SH7203) || \ | 139 | defined(CONFIG_CPU_SUBTYPE_SH7203) || \ |
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index ab69c1bf36a..c2747bc88c6 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c | |||
| @@ -2164,19 +2164,20 @@ static void __exit panel_cleanup_module(void) | |||
| 2164 | if (scan_timer.function != NULL) | 2164 | if (scan_timer.function != NULL) |
| 2165 | del_timer(&scan_timer); | 2165 | del_timer(&scan_timer); |
| 2166 | 2166 | ||
| 2167 | if (keypad_enabled) | 2167 | if (pprt != NULL) { |
| 2168 | misc_deregister(&keypad_dev); | 2168 | if (keypad_enabled) |
| 2169 | misc_deregister(&keypad_dev); | ||
| 2170 | |||
| 2171 | if (lcd_enabled) { | ||
| 2172 | panel_lcd_print("\x0cLCD driver " PANEL_VERSION | ||
| 2173 | "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); | ||
| 2174 | misc_deregister(&lcd_dev); | ||
| 2175 | } | ||
| 2169 | 2176 | ||
| 2170 | if (lcd_enabled) { | 2177 | /* TODO: free all input signals */ |
| 2171 | panel_lcd_print("\x0cLCD driver " PANEL_VERSION | 2178 | parport_release(pprt); |
| 2172 | "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); | 2179 | parport_unregister_device(pprt); |
| 2173 | misc_deregister(&lcd_dev); | ||
| 2174 | } | 2180 | } |
| 2175 | |||
| 2176 | /* TODO: free all input signals */ | ||
| 2177 | |||
| 2178 | parport_release(pprt); | ||
| 2179 | parport_unregister_device(pprt); | ||
| 2180 | parport_unregister_driver(&panel_driver); | 2181 | parport_unregister_driver(&panel_driver); |
| 2181 | } | 2182 | } |
| 2182 | 2183 | ||
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 79c225acd1a..f636296b54b 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config RTL8187SE | 1 | config RTL8187SE |
| 2 | tristate "RealTek RTL8187SE Wireless LAN NIC driver" | 2 | tristate "RealTek RTL8187SE Wireless LAN NIC driver" |
| 3 | depends on PCI | 3 | depends on PCI |
| 4 | depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS | ||
| 4 | default N | 5 | default N |
| 5 | ---help--- | 6 | ---help--- |
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c index af64cfbe16d..7370296225e 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c | |||
| @@ -234,20 +234,21 @@ out: | |||
| 234 | void ieee80211_crypto_deinit(void) | 234 | void ieee80211_crypto_deinit(void) |
| 235 | { | 235 | { |
| 236 | struct list_head *ptr, *n; | 236 | struct list_head *ptr, *n; |
| 237 | struct ieee80211_crypto_alg *alg = NULL; | ||
| 237 | 238 | ||
| 238 | if (hcrypt == NULL) | 239 | if (hcrypt == NULL) |
| 239 | return; | 240 | return; |
| 240 | 241 | ||
| 241 | for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; | 242 | list_for_each_safe(ptr, n, &hcrypt->algs) { |
| 242 | ptr = n, n = ptr->next) { | 243 | alg = list_entry(ptr, struct ieee80211_crypto_alg, list); |
| 243 | struct ieee80211_crypto_alg *alg = | 244 | if (alg) { |
| 244 | (struct ieee80211_crypto_alg *) ptr; | 245 | list_del(ptr); |
| 245 | list_del(ptr); | 246 | printk(KERN_DEBUG |
| 246 | printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " | 247 | "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n", |
| 247 | "'%s' (deinit)\n", alg->ops->name); | 248 | alg->ops->name); |
| 248 | kfree(alg); | 249 | kfree(alg); |
| 250 | } | ||
| 249 | } | 251 | } |
| 250 | |||
| 251 | kfree(hcrypt); | 252 | kfree(hcrypt); |
| 252 | } | 253 | } |
| 253 | 254 | ||
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 94534955e38..66de5cc8ddf 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
| @@ -6161,10 +6161,10 @@ static void __exit rtl8180_pci_module_exit(void) | |||
| 6161 | { | 6161 | { |
| 6162 | pci_unregister_driver (&rtl8180_pci_driver); | 6162 | pci_unregister_driver (&rtl8180_pci_driver); |
| 6163 | rtl8180_proc_module_remove(); | 6163 | rtl8180_proc_module_remove(); |
| 6164 | ieee80211_crypto_deinit(); | ||
| 6165 | ieee80211_crypto_tkip_exit(); | 6164 | ieee80211_crypto_tkip_exit(); |
| 6166 | ieee80211_crypto_ccmp_exit(); | 6165 | ieee80211_crypto_ccmp_exit(); |
| 6167 | ieee80211_crypto_wep_exit(); | 6166 | ieee80211_crypto_wep_exit(); |
| 6167 | ieee80211_crypto_deinit(); | ||
| 6168 | DMESG("Exiting"); | 6168 | DMESG("Exiting"); |
| 6169 | } | 6169 | } |
| 6170 | 6170 | ||
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index b003f9a7e15..f716b2e92b6 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c | |||
| @@ -319,16 +319,18 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 319 | struct usb_device *udev = interface_to_usbdev(intf); | 319 | struct usb_device *udev = interface_to_usbdev(intf); |
| 320 | struct wbsoft_priv *priv; | 320 | struct wbsoft_priv *priv; |
| 321 | struct ieee80211_hw *dev; | 321 | struct ieee80211_hw *dev; |
| 322 | int err; | 322 | int nr, err; |
| 323 | 323 | ||
| 324 | usb_get_dev(udev); | 324 | usb_get_dev(udev); |
| 325 | 325 | ||
| 326 | // 20060630.2 Check the device if it already be opened | 326 | // 20060630.2 Check the device if it already be opened |
| 327 | err = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ), | 327 | nr = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ), |
| 328 | 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, | 328 | 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, |
| 329 | 0x0, 0x400, <mp, 4, HZ*100 ); | 329 | 0x0, 0x400, <mp, 4, HZ*100 ); |
| 330 | if (err) | 330 | if (nr < 0) { |
| 331 | err = nr; | ||
| 331 | goto error; | 332 | goto error; |
| 333 | } | ||
| 332 | 334 | ||
| 333 | ltmp = cpu_to_le32(ltmp); | 335 | ltmp = cpu_to_le32(ltmp); |
| 334 | if (ltmp) { // Is already initialized? | 336 | if (ltmp) { // Is already initialized? |
| @@ -337,8 +339,10 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 337 | } | 339 | } |
| 338 | 340 | ||
| 339 | dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops); | 341 | dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops); |
| 340 | if (!dev) | 342 | if (!dev) { |
| 343 | err = -ENOMEM; | ||
| 341 | goto error; | 344 | goto error; |
| 345 | } | ||
| 342 | 346 | ||
| 343 | priv = dev->priv; | 347 | priv = dev->priv; |
| 344 | 348 | ||
| @@ -369,9 +373,11 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 369 | } | 373 | } |
| 370 | 374 | ||
| 371 | dev->extra_tx_headroom = 12; /* FIXME */ | 375 | dev->extra_tx_headroom = 12; /* FIXME */ |
| 372 | dev->flags = 0; | 376 | dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; |
| 377 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
| 373 | 378 | ||
| 374 | dev->channel_change_time = 1000; | 379 | dev->channel_change_time = 1000; |
| 380 | dev->max_signal = 100; | ||
| 375 | dev->queues = 1; | 381 | dev->queues = 1; |
| 376 | 382 | ||
| 377 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz; | 383 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz; |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 326dd7f65ee..b3d5a23ab56 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -1376,6 +1376,15 @@ static struct usb_device_id acm_ids[] = { | |||
| 1376 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ | 1376 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ |
| 1377 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1377 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1378 | }, | 1378 | }, |
| 1379 | { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ | ||
| 1380 | }, | ||
| 1381 | { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ | ||
| 1382 | .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on | ||
| 1383 | data interface instead of | ||
| 1384 | communications interface. | ||
| 1385 | Maybe we should define a new | ||
| 1386 | quirk for this. */ | ||
| 1387 | }, | ||
| 1379 | 1388 | ||
| 1380 | /* control interfaces with various AT-command sets */ | 1389 | /* control interfaces with various AT-command sets */ |
| 1381 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1390 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 31fb204f44c..49e7f56e0d7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, | |||
| 653 | if (result <= 0 && result != -ETIMEDOUT) | 653 | if (result <= 0 && result != -ETIMEDOUT) |
| 654 | continue; | 654 | continue; |
| 655 | if (result > 1 && ((u8 *)buf)[1] != type) { | 655 | if (result > 1 && ((u8 *)buf)[1] != type) { |
| 656 | result = -EPROTO; | 656 | result = -ENODATA; |
| 657 | continue; | 657 | continue; |
| 658 | } | 658 | } |
| 659 | break; | 659 | break; |
| @@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, | |||
| 696 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | 696 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, |
| 697 | (USB_DT_STRING << 8) + index, langid, buf, size, | 697 | (USB_DT_STRING << 8) + index, langid, buf, size, |
| 698 | USB_CTRL_GET_TIMEOUT); | 698 | USB_CTRL_GET_TIMEOUT); |
| 699 | if (!(result == 0 || result == -EPIPE)) | 699 | if (result == 0 || result == -EPIPE) |
| 700 | break; | 700 | continue; |
| 701 | if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) { | ||
| 702 | result = -ENODATA; | ||
| 703 | continue; | ||
| 704 | } | ||
| 705 | break; | ||
| 701 | } | 706 | } |
| 702 | return result; | 707 | return result; |
| 703 | } | 708 | } |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 3219d137340..e55fef52a5d 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
| @@ -191,6 +191,7 @@ config USB_GADGET_OMAP | |||
| 191 | boolean "OMAP USB Device Controller" | 191 | boolean "OMAP USB Device Controller" |
| 192 | depends on ARCH_OMAP | 192 | depends on ARCH_OMAP |
| 193 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG | 193 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG |
| 194 | select USB_OTG_UTILS if ARCH_OMAP | ||
| 194 | help | 195 | help |
| 195 | Many Texas Instruments OMAP processors have flexible full | 196 | Many Texas Instruments OMAP processors have flexible full |
| 196 | speed USB device controllers, with support for up to 30 | 197 | speed USB device controllers, with support for up to 30 |
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 80c2e7e9622..38aa896cc5d 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c | |||
| @@ -366,9 +366,9 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) | |||
| 366 | f->hs_descriptors = usb_copy_descriptors(hs_function); | 366 | f->hs_descriptors = usb_copy_descriptors(hs_function); |
| 367 | 367 | ||
| 368 | obex->hs.obex_in = usb_find_endpoint(hs_function, | 368 | obex->hs.obex_in = usb_find_endpoint(hs_function, |
| 369 | f->descriptors, &obex_hs_ep_in_desc); | 369 | f->hs_descriptors, &obex_hs_ep_in_desc); |
| 370 | obex->hs.obex_out = usb_find_endpoint(hs_function, | 370 | obex->hs.obex_out = usb_find_endpoint(hs_function, |
| 371 | f->descriptors, &obex_hs_ep_out_desc); | 371 | f->hs_descriptors, &obex_hs_ep_out_desc); |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | /* Avoid letting this gadget enumerate until the userspace | 374 | /* Avoid letting this gadget enumerate until the userspace |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index b10fa31cc91..1ab9dac7e12 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
| @@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
| 3879 | mod_data.protocol_type = USB_SC_SCSI; | 3879 | mod_data.protocol_type = USB_SC_SCSI; |
| 3880 | mod_data.protocol_name = "Transparent SCSI"; | 3880 | mod_data.protocol_name = "Transparent SCSI"; |
| 3881 | 3881 | ||
| 3882 | if (gadget_is_sh(fsg->gadget)) | 3882 | /* Some peripheral controllers are known not to be able to |
| 3883 | * halt bulk endpoints correctly. If one of them is present, | ||
| 3884 | * disable stalls. | ||
| 3885 | */ | ||
| 3886 | if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget)) | ||
| 3883 | mod_data.can_stall = 0; | 3887 | mod_data.can_stall = 0; |
| 3884 | 3888 | ||
| 3885 | if (mod_data.release == 0xffff) { // Parameter wasn't set | 3889 | if (mod_data.release == 0xffff) { // Parameter wasn't set |
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index f3c6703cffd..d8d9a52a44b 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c | |||
| @@ -404,7 +404,10 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num, | |||
| 404 | } | 404 | } |
| 405 | if (zlt) | 405 | if (zlt) |
| 406 | tmp |= EP_QUEUE_HEAD_ZLT_SEL; | 406 | tmp |= EP_QUEUE_HEAD_ZLT_SEL; |
| 407 | |||
| 407 | p_QH->max_pkt_length = cpu_to_le32(tmp); | 408 | p_QH->max_pkt_length = cpu_to_le32(tmp); |
| 409 | p_QH->next_dtd_ptr = 1; | ||
| 410 | p_QH->size_ioc_int_sts = 0; | ||
| 408 | 411 | ||
| 409 | return; | 412 | return; |
| 410 | } | 413 | } |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4725d15d096..e551bb38852 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
| 485 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 485 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
| 486 | */ | 486 | */ |
| 487 | ehci->periodic_size = DEFAULT_I_TDPS; | 487 | ehci->periodic_size = DEFAULT_I_TDPS; |
| 488 | INIT_LIST_HEAD(&ehci->cached_itd_list); | ||
| 488 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) | 489 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) |
| 489 | return retval; | 490 | return retval; |
| 490 | 491 | ||
| @@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
| 497 | 498 | ||
| 498 | ehci->reclaim = NULL; | 499 | ehci->reclaim = NULL; |
| 499 | ehci->next_uframe = -1; | 500 | ehci->next_uframe = -1; |
| 501 | ehci->clock_frame = -1; | ||
| 500 | 502 | ||
| 501 | /* | 503 | /* |
| 502 | * dedicate a qh for the async ring head, since we couldn't unlink | 504 | * dedicate a qh for the async ring head, since we couldn't unlink |
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 0431397836f..10d52919abb 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
| @@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh) | |||
| 128 | 128 | ||
| 129 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) | 129 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) |
| 130 | { | 130 | { |
| 131 | free_cached_itd_list(ehci); | ||
| 131 | if (ehci->async) | 132 | if (ehci->async) |
| 132 | qh_put (ehci->async); | 133 | qh_put (ehci->async); |
| 133 | ehci->async = NULL; | 134 | ehci->async = NULL; |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a081ee65bde..07bcb931021 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) | |||
| 1004 | 1004 | ||
| 1005 | is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; | 1005 | is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; |
| 1006 | stream->bEndpointAddress &= 0x0f; | 1006 | stream->bEndpointAddress &= 0x0f; |
| 1007 | stream->ep->hcpriv = NULL; | 1007 | if (stream->ep) |
| 1008 | stream->ep->hcpriv = NULL; | ||
| 1008 | 1009 | ||
| 1009 | if (stream->rescheduled) { | 1010 | if (stream->rescheduled) { |
| 1010 | ehci_info (ehci, "ep%d%s-iso rescheduled " | 1011 | ehci_info (ehci, "ep%d%s-iso rescheduled " |
| @@ -1653,14 +1654,28 @@ itd_complete ( | |||
| 1653 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 1654 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
| 1654 | } | 1655 | } |
| 1655 | iso_stream_put (ehci, stream); | 1656 | iso_stream_put (ehci, stream); |
| 1656 | /* OK to recycle this ITD now that its completion callback ran. */ | 1657 | |
| 1657 | done: | 1658 | done: |
| 1658 | usb_put_urb(urb); | 1659 | usb_put_urb(urb); |
| 1659 | itd->urb = NULL; | 1660 | itd->urb = NULL; |
| 1660 | itd->stream = NULL; | 1661 | if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { |
| 1661 | list_move(&itd->itd_list, &stream->free_list); | 1662 | /* OK to recycle this ITD now. */ |
| 1662 | iso_stream_put(ehci, stream); | 1663 | itd->stream = NULL; |
| 1663 | 1664 | list_move(&itd->itd_list, &stream->free_list); | |
| 1665 | iso_stream_put(ehci, stream); | ||
| 1666 | } else { | ||
| 1667 | /* HW might remember this ITD, so we can't recycle it yet. | ||
| 1668 | * Move it to a safe place until a new frame starts. | ||
| 1669 | */ | ||
| 1670 | list_move(&itd->itd_list, &ehci->cached_itd_list); | ||
| 1671 | if (stream->refcount == 2) { | ||
| 1672 | /* If iso_stream_put() were called here, stream | ||
| 1673 | * would be freed. Instead, just prevent reuse. | ||
| 1674 | */ | ||
| 1675 | stream->ep->hcpriv = NULL; | ||
| 1676 | stream->ep = NULL; | ||
| 1677 | } | ||
| 1678 | } | ||
| 1664 | return retval; | 1679 | return retval; |
| 1665 | } | 1680 | } |
| 1666 | 1681 | ||
| @@ -2101,6 +2116,20 @@ done: | |||
| 2101 | 2116 | ||
| 2102 | /*-------------------------------------------------------------------------*/ | 2117 | /*-------------------------------------------------------------------------*/ |
| 2103 | 2118 | ||
| 2119 | static void free_cached_itd_list(struct ehci_hcd *ehci) | ||
| 2120 | { | ||
| 2121 | struct ehci_itd *itd, *n; | ||
| 2122 | |||
| 2123 | list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { | ||
| 2124 | struct ehci_iso_stream *stream = itd->stream; | ||
| 2125 | itd->stream = NULL; | ||
| 2126 | list_move(&itd->itd_list, &stream->free_list); | ||
| 2127 | iso_stream_put(ehci, stream); | ||
| 2128 | } | ||
| 2129 | } | ||
| 2130 | |||
| 2131 | /*-------------------------------------------------------------------------*/ | ||
| 2132 | |||
| 2104 | static void | 2133 | static void |
| 2105 | scan_periodic (struct ehci_hcd *ehci) | 2134 | scan_periodic (struct ehci_hcd *ehci) |
| 2106 | { | 2135 | { |
| @@ -2115,10 +2144,17 @@ scan_periodic (struct ehci_hcd *ehci) | |||
| 2115 | * Touches as few pages as possible: cache-friendly. | 2144 | * Touches as few pages as possible: cache-friendly. |
| 2116 | */ | 2145 | */ |
| 2117 | now_uframe = ehci->next_uframe; | 2146 | now_uframe = ehci->next_uframe; |
| 2118 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 2147 | if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { |
| 2119 | clock = ehci_readl(ehci, &ehci->regs->frame_index); | 2148 | clock = ehci_readl(ehci, &ehci->regs->frame_index); |
| 2120 | else | 2149 | clock_frame = (clock >> 3) % ehci->periodic_size; |
| 2150 | } else { | ||
| 2121 | clock = now_uframe + mod - 1; | 2151 | clock = now_uframe + mod - 1; |
| 2152 | clock_frame = -1; | ||
| 2153 | } | ||
| 2154 | if (ehci->clock_frame != clock_frame) { | ||
| 2155 | free_cached_itd_list(ehci); | ||
| 2156 | ehci->clock_frame = clock_frame; | ||
| 2157 | } | ||
| 2122 | clock %= mod; | 2158 | clock %= mod; |
| 2123 | clock_frame = clock >> 3; | 2159 | clock_frame = clock >> 3; |
| 2124 | 2160 | ||
| @@ -2277,6 +2313,10 @@ restart: | |||
| 2277 | /* rescan the rest of this frame, then ... */ | 2313 | /* rescan the rest of this frame, then ... */ |
| 2278 | clock = now; | 2314 | clock = now; |
| 2279 | clock_frame = clock >> 3; | 2315 | clock_frame = clock >> 3; |
| 2316 | if (ehci->clock_frame != clock_frame) { | ||
| 2317 | free_cached_itd_list(ehci); | ||
| 2318 | ehci->clock_frame = clock_frame; | ||
| 2319 | } | ||
| 2280 | } else { | 2320 | } else { |
| 2281 | now_uframe++; | 2321 | now_uframe++; |
| 2282 | now_uframe %= mod; | 2322 | now_uframe %= mod; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index fb7054ccf4f..262b00c9b33 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
| @@ -87,6 +87,10 @@ struct ehci_hcd { /* one per controller */ | |||
| 87 | int next_uframe; /* scan periodic, start here */ | 87 | int next_uframe; /* scan periodic, start here */ |
| 88 | unsigned periodic_sched; /* periodic activity count */ | 88 | unsigned periodic_sched; /* periodic activity count */ |
| 89 | 89 | ||
| 90 | /* list of itds completed while clock_frame was still active */ | ||
| 91 | struct list_head cached_itd_list; | ||
| 92 | unsigned clock_frame; | ||
| 93 | |||
| 90 | /* per root hub port */ | 94 | /* per root hub port */ |
| 91 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; | 95 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; |
| 92 | 96 | ||
| @@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
| 220 | } | 224 | } |
| 221 | } | 225 | } |
| 222 | 226 | ||
| 227 | static void free_cached_itd_list(struct ehci_hcd *ehci); | ||
| 228 | |||
| 223 | /*-------------------------------------------------------------------------*/ | 229 | /*-------------------------------------------------------------------------*/ |
| 224 | 230 | ||
| 225 | #include <linux/usb/ehci_def.h> | 231 | #include <linux/usb/ehci_def.h> |
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 5a8fd5d57a1..2dc7606f319 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
| @@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb) | |||
| 377 | u32 revision; | 377 | u32 revision; |
| 378 | 378 | ||
| 379 | musb->mregs += DAVINCI_BASE_OFFSET; | 379 | musb->mregs += DAVINCI_BASE_OFFSET; |
| 380 | #if 0 | ||
| 381 | /* REVISIT there's something odd about clocking, this | ||
| 382 | * didn't appear do the job ... | ||
| 383 | */ | ||
| 384 | musb->clock = clk_get(pDevice, "usb"); | ||
| 385 | if (IS_ERR(musb->clock)) | ||
| 386 | return PTR_ERR(musb->clock); | ||
| 387 | 380 | ||
| 388 | status = clk_enable(musb->clock); | 381 | clk_enable(musb->clock); |
| 389 | if (status < 0) | ||
| 390 | return -ENODEV; | ||
| 391 | #endif | ||
| 392 | 382 | ||
| 393 | /* returns zero if e.g. not clocked */ | 383 | /* returns zero if e.g. not clocked */ |
| 394 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); | 384 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); |
| @@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb) | |||
| 453 | } | 443 | } |
| 454 | 444 | ||
| 455 | phy_off(); | 445 | phy_off(); |
| 446 | |||
| 447 | clk_disable(musb->clock); | ||
| 448 | |||
| 456 | return 0; | 449 | return 0; |
| 457 | } | 450 | } |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2cc34fa05b7..af77e465900 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
| @@ -115,7 +115,7 @@ | |||
| 115 | 115 | ||
| 116 | 116 | ||
| 117 | unsigned musb_debug; | 117 | unsigned musb_debug; |
| 118 | module_param(musb_debug, uint, S_IRUGO | S_IWUSR); | 118 | module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR); |
| 119 | MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); | 119 | MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); |
| 120 | 120 | ||
| 121 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" | 121 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" |
| @@ -767,6 +767,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | |||
| 767 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 767 | #ifdef CONFIG_USB_MUSB_HDRC_HCD |
| 768 | case OTG_STATE_A_HOST: | 768 | case OTG_STATE_A_HOST: |
| 769 | case OTG_STATE_A_SUSPEND: | 769 | case OTG_STATE_A_SUSPEND: |
| 770 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | ||
| 770 | musb_root_disconnect(musb); | 771 | musb_root_disconnect(musb); |
| 771 | if (musb->a_wait_bcon != 0) | 772 | if (musb->a_wait_bcon != 0) |
| 772 | musb_platform_try_idle(musb, jiffies | 773 | musb_platform_try_idle(musb, jiffies |
| @@ -1815,7 +1816,7 @@ static void musb_free(struct musb *musb) | |||
| 1815 | #ifdef CONFIG_SYSFS | 1816 | #ifdef CONFIG_SYSFS |
| 1816 | device_remove_file(musb->controller, &dev_attr_mode); | 1817 | device_remove_file(musb->controller, &dev_attr_mode); |
| 1817 | device_remove_file(musb->controller, &dev_attr_vbus); | 1818 | device_remove_file(musb->controller, &dev_attr_vbus); |
| 1818 | #ifdef CONFIG_USB_MUSB_OTG | 1819 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
| 1819 | device_remove_file(musb->controller, &dev_attr_srp); | 1820 | device_remove_file(musb->controller, &dev_attr_srp); |
| 1820 | #endif | 1821 | #endif |
| 1821 | #endif | 1822 | #endif |
| @@ -2063,7 +2064,7 @@ fail2: | |||
| 2063 | #ifdef CONFIG_SYSFS | 2064 | #ifdef CONFIG_SYSFS |
| 2064 | device_remove_file(musb->controller, &dev_attr_mode); | 2065 | device_remove_file(musb->controller, &dev_attr_mode); |
| 2065 | device_remove_file(musb->controller, &dev_attr_vbus); | 2066 | device_remove_file(musb->controller, &dev_attr_vbus); |
| 2066 | #ifdef CONFIG_USB_MUSB_OTG | 2067 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
| 2067 | device_remove_file(musb->controller, &dev_attr_srp); | 2068 | device_remove_file(musb->controller, &dev_attr_srp); |
| 2068 | #endif | 2069 | #endif |
| 2069 | #endif | 2070 | #endif |
| @@ -2243,10 +2244,10 @@ static int __init musb_init(void) | |||
| 2243 | return platform_driver_probe(&musb_driver, musb_probe); | 2244 | return platform_driver_probe(&musb_driver, musb_probe); |
| 2244 | } | 2245 | } |
| 2245 | 2246 | ||
| 2246 | /* make us init after usbcore and before usb | 2247 | /* make us init after usbcore and i2c (transceivers, regulators, etc) |
| 2247 | * gadget and host-side drivers start to register | 2248 | * and before usb gadget and host-side drivers start to register |
| 2248 | */ | 2249 | */ |
| 2249 | subsys_initcall(musb_init); | 2250 | fs_initcall(musb_init); |
| 2250 | 2251 | ||
| 2251 | static void __exit musb_cleanup(void) | 2252 | static void __exit musb_cleanup(void) |
| 2252 | { | 2253 | { |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 4ea30538798..c7ebd0867fc 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
| @@ -575,7 +575,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
| 575 | struct usb_request *request = &req->request; | 575 | struct usb_request *request = &req->request; |
| 576 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; | 576 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; |
| 577 | void __iomem *epio = musb->endpoints[epnum].regs; | 577 | void __iomem *epio = musb->endpoints[epnum].regs; |
| 578 | u16 fifo_count = 0; | 578 | unsigned fifo_count = 0; |
| 579 | u16 len = musb_ep->packet_sz; | 579 | u16 len = musb_ep->packet_sz; |
| 580 | 580 | ||
| 581 | csr = musb_readw(epio, MUSB_RXCSR); | 581 | csr = musb_readw(epio, MUSB_RXCSR); |
| @@ -687,7 +687,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
| 687 | len, fifo_count, | 687 | len, fifo_count, |
| 688 | musb_ep->packet_sz); | 688 | musb_ep->packet_sz); |
| 689 | 689 | ||
| 690 | fifo_count = min(len, fifo_count); | 690 | fifo_count = min_t(unsigned, len, fifo_count); |
| 691 | 691 | ||
| 692 | #ifdef CONFIG_USB_TUSB_OMAP_DMA | 692 | #ifdef CONFIG_USB_TUSB_OMAP_DMA |
| 693 | if (tusb_dma_omap() && musb_ep->dma) { | 693 | if (tusb_dma_omap() && musb_ep->dma) { |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index a035ceccf95..6dbbd0786a6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
| @@ -335,16 +335,11 @@ musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb) | |||
| 335 | static struct musb_qh * | 335 | static struct musb_qh * |
| 336 | musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | 336 | musb_giveback(struct musb_qh *qh, struct urb *urb, int status) |
| 337 | { | 337 | { |
| 338 | int is_in; | ||
| 339 | struct musb_hw_ep *ep = qh->hw_ep; | 338 | struct musb_hw_ep *ep = qh->hw_ep; |
| 340 | struct musb *musb = ep->musb; | 339 | struct musb *musb = ep->musb; |
| 340 | int is_in = usb_pipein(urb->pipe); | ||
| 341 | int ready = qh->is_ready; | 341 | int ready = qh->is_ready; |
| 342 | 342 | ||
| 343 | if (ep->is_shared_fifo) | ||
| 344 | is_in = 1; | ||
| 345 | else | ||
| 346 | is_in = usb_pipein(urb->pipe); | ||
| 347 | |||
| 348 | /* save toggle eagerly, for paranoia */ | 343 | /* save toggle eagerly, for paranoia */ |
| 349 | switch (qh->type) { | 344 | switch (qh->type) { |
| 350 | case USB_ENDPOINT_XFER_BULK: | 345 | case USB_ENDPOINT_XFER_BULK: |
| @@ -432,7 +427,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, | |||
| 432 | else | 427 | else |
| 433 | qh = musb_giveback(qh, urb, urb->status); | 428 | qh = musb_giveback(qh, urb, urb->status); |
| 434 | 429 | ||
| 435 | if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) { | 430 | if (qh != NULL && qh->is_ready) { |
| 436 | DBG(4, "... next ep%d %cX urb %p\n", | 431 | DBG(4, "... next ep%d %cX urb %p\n", |
| 437 | hw_ep->epnum, is_in ? 'R' : 'T', | 432 | hw_ep->epnum, is_in ? 'R' : 'T', |
| 438 | next_urb(qh)); | 433 | next_urb(qh)); |
| @@ -942,8 +937,8 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) | |||
| 942 | switch (musb->ep0_stage) { | 937 | switch (musb->ep0_stage) { |
| 943 | case MUSB_EP0_IN: | 938 | case MUSB_EP0_IN: |
| 944 | fifo_dest = urb->transfer_buffer + urb->actual_length; | 939 | fifo_dest = urb->transfer_buffer + urb->actual_length; |
| 945 | fifo_count = min(len, ((u16) (urb->transfer_buffer_length | 940 | fifo_count = min_t(size_t, len, urb->transfer_buffer_length - |
| 946 | - urb->actual_length))); | 941 | urb->actual_length); |
| 947 | if (fifo_count < len) | 942 | if (fifo_count < len) |
| 948 | urb->status = -EOVERFLOW; | 943 | urb->status = -EOVERFLOW; |
| 949 | 944 | ||
| @@ -976,10 +971,9 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) | |||
| 976 | } | 971 | } |
| 977 | /* FALLTHROUGH */ | 972 | /* FALLTHROUGH */ |
| 978 | case MUSB_EP0_OUT: | 973 | case MUSB_EP0_OUT: |
| 979 | fifo_count = min(qh->maxpacket, ((u16) | 974 | fifo_count = min_t(size_t, qh->maxpacket, |
| 980 | (urb->transfer_buffer_length | 975 | urb->transfer_buffer_length - |
| 981 | - urb->actual_length))); | 976 | urb->actual_length); |
| 982 | |||
| 983 | if (fifo_count) { | 977 | if (fifo_count) { |
| 984 | fifo_dest = (u8 *) (urb->transfer_buffer | 978 | fifo_dest = (u8 *) (urb->transfer_buffer |
| 985 | + urb->actual_length); | 979 | + urb->actual_length); |
| @@ -1161,7 +1155,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
| 1161 | struct urb *urb; | 1155 | struct urb *urb; |
| 1162 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; | 1156 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; |
| 1163 | void __iomem *epio = hw_ep->regs; | 1157 | void __iomem *epio = hw_ep->regs; |
| 1164 | struct musb_qh *qh = hw_ep->out_qh; | 1158 | struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh |
| 1159 | : hw_ep->out_qh; | ||
| 1165 | u32 status = 0; | 1160 | u32 status = 0; |
| 1166 | void __iomem *mbase = musb->mregs; | 1161 | void __iomem *mbase = musb->mregs; |
| 1167 | struct dma_channel *dma; | 1162 | struct dma_channel *dma; |
| @@ -1308,7 +1303,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
| 1308 | * packets before updating TXCSR ... other docs disagree ... | 1303 | * packets before updating TXCSR ... other docs disagree ... |
| 1309 | */ | 1304 | */ |
| 1310 | /* PIO: start next packet in this URB */ | 1305 | /* PIO: start next packet in this URB */ |
| 1311 | wLength = min(qh->maxpacket, (u16) wLength); | 1306 | if (wLength > qh->maxpacket) |
| 1307 | wLength = qh->maxpacket; | ||
| 1312 | musb_write_fifo(hw_ep, wLength, buf); | 1308 | musb_write_fifo(hw_ep, wLength, buf); |
| 1313 | qh->segsize = wLength; | 1309 | qh->segsize = wLength; |
| 1314 | 1310 | ||
| @@ -1867,19 +1863,21 @@ static int musb_urb_enqueue( | |||
| 1867 | } | 1863 | } |
| 1868 | qh->type_reg = type_reg; | 1864 | qh->type_reg = type_reg; |
| 1869 | 1865 | ||
| 1870 | /* precompute rxinterval/txinterval register */ | 1866 | /* Precompute RXINTERVAL/TXINTERVAL register */ |
| 1871 | interval = min((u8)16, epd->bInterval); /* log encoding */ | ||
| 1872 | switch (qh->type) { | 1867 | switch (qh->type) { |
| 1873 | case USB_ENDPOINT_XFER_INT: | 1868 | case USB_ENDPOINT_XFER_INT: |
| 1874 | /* fullspeed uses linear encoding */ | 1869 | /* |
| 1875 | if (USB_SPEED_FULL == urb->dev->speed) { | 1870 | * Full/low speeds use the linear encoding, |
| 1876 | interval = epd->bInterval; | 1871 | * high speed uses the logarithmic encoding. |
| 1877 | if (!interval) | 1872 | */ |
| 1878 | interval = 1; | 1873 | if (urb->dev->speed <= USB_SPEED_FULL) { |
| 1874 | interval = max_t(u8, epd->bInterval, 1); | ||
| 1875 | break; | ||
| 1879 | } | 1876 | } |
| 1880 | /* FALLTHROUGH */ | 1877 | /* FALLTHROUGH */ |
| 1881 | case USB_ENDPOINT_XFER_ISOC: | 1878 | case USB_ENDPOINT_XFER_ISOC: |
| 1882 | /* iso always uses log encoding */ | 1879 | /* ISO always uses logarithmic encoding */ |
| 1880 | interval = min_t(u8, epd->bInterval, 16); | ||
| 1883 | break; | 1881 | break; |
| 1884 | default: | 1882 | default: |
| 1885 | /* REVISIT we actually want to use NAK limits, hinting to the | 1883 | /* REVISIT we actually want to use NAK limits, hinting to the |
| @@ -2037,9 +2035,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
| 2037 | goto done; | 2035 | goto done; |
| 2038 | 2036 | ||
| 2039 | /* Any URB not actively programmed into endpoint hardware can be | 2037 | /* Any URB not actively programmed into endpoint hardware can be |
| 2040 | * immediately given back. Such an URB must be at the head of its | 2038 | * immediately given back; that's any URB not at the head of an |
| 2041 | * endpoint queue, unless someday we get real DMA queues. And even | 2039 | * endpoint queue, unless someday we get real DMA queues. And even |
| 2042 | * then, it might not be known to the hardware... | 2040 | * if it's at the head, it might not be known to the hardware... |
| 2043 | * | 2041 | * |
| 2044 | * Otherwise abort current transfer, pending dma, etc.; urb->status | 2042 | * Otherwise abort current transfer, pending dma, etc.; urb->status |
| 2045 | * has already been updated. This is a synchronous abort; it'd be | 2043 | * has already been updated. This is a synchronous abort; it'd be |
| @@ -2078,6 +2076,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
| 2078 | qh->is_ready = 0; | 2076 | qh->is_ready = 0; |
| 2079 | __musb_giveback(musb, urb, 0); | 2077 | __musb_giveback(musb, urb, 0); |
| 2080 | qh->is_ready = ready; | 2078 | qh->is_ready = ready; |
| 2079 | |||
| 2080 | /* If nothing else (usually musb_giveback) is using it | ||
| 2081 | * and its URB list has emptied, recycle this qh. | ||
| 2082 | */ | ||
| 2083 | if (ready && list_empty(&qh->hep->urb_list)) { | ||
| 2084 | qh->hep->hcpriv = NULL; | ||
| 2085 | list_del(&qh->ring); | ||
| 2086 | kfree(qh); | ||
| 2087 | } | ||
| 2081 | } else | 2088 | } else |
| 2082 | ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); | 2089 | ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); |
| 2083 | done: | 2090 | done: |
| @@ -2093,15 +2100,16 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | |||
| 2093 | unsigned long flags; | 2100 | unsigned long flags; |
| 2094 | struct musb *musb = hcd_to_musb(hcd); | 2101 | struct musb *musb = hcd_to_musb(hcd); |
| 2095 | u8 is_in = epnum & USB_DIR_IN; | 2102 | u8 is_in = epnum & USB_DIR_IN; |
| 2096 | struct musb_qh *qh = hep->hcpriv; | 2103 | struct musb_qh *qh; |
| 2097 | struct urb *urb, *tmp; | 2104 | struct urb *urb; |
| 2098 | struct list_head *sched; | 2105 | struct list_head *sched; |
| 2099 | 2106 | ||
| 2100 | if (!qh) | ||
| 2101 | return; | ||
| 2102 | |||
| 2103 | spin_lock_irqsave(&musb->lock, flags); | 2107 | spin_lock_irqsave(&musb->lock, flags); |
| 2104 | 2108 | ||
| 2109 | qh = hep->hcpriv; | ||
| 2110 | if (qh == NULL) | ||
| 2111 | goto exit; | ||
| 2112 | |||
| 2105 | switch (qh->type) { | 2113 | switch (qh->type) { |
| 2106 | case USB_ENDPOINT_XFER_CONTROL: | 2114 | case USB_ENDPOINT_XFER_CONTROL: |
| 2107 | sched = &musb->control; | 2115 | sched = &musb->control; |
| @@ -2135,13 +2143,28 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | |||
| 2135 | 2143 | ||
| 2136 | /* cleanup */ | 2144 | /* cleanup */ |
| 2137 | musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); | 2145 | musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); |
| 2138 | } else | ||
| 2139 | urb = NULL; | ||
| 2140 | 2146 | ||
| 2141 | /* then just nuke all the others */ | 2147 | /* Then nuke all the others ... and advance the |
| 2142 | list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list) | 2148 | * queue on hw_ep (e.g. bulk ring) when we're done. |
| 2143 | musb_giveback(qh, urb, -ESHUTDOWN); | 2149 | */ |
| 2150 | while (!list_empty(&hep->urb_list)) { | ||
| 2151 | urb = next_urb(qh); | ||
| 2152 | urb->status = -ESHUTDOWN; | ||
| 2153 | musb_advance_schedule(musb, urb, qh->hw_ep, is_in); | ||
| 2154 | } | ||
| 2155 | } else { | ||
| 2156 | /* Just empty the queue; the hardware is busy with | ||
| 2157 | * other transfers, and since !qh->is_ready nothing | ||
| 2158 | * will activate any of these as it advances. | ||
| 2159 | */ | ||
| 2160 | while (!list_empty(&hep->urb_list)) | ||
| 2161 | __musb_giveback(musb, next_urb(qh), -ESHUTDOWN); | ||
| 2144 | 2162 | ||
| 2163 | hep->hcpriv = NULL; | ||
| 2164 | list_del(&qh->ring); | ||
| 2165 | kfree(qh); | ||
| 2166 | } | ||
| 2167 | exit: | ||
| 2145 | spin_unlock_irqrestore(&musb->lock, flags); | 2168 | spin_unlock_irqrestore(&musb->lock, flags); |
| 2146 | } | 2169 | } |
| 2147 | 2170 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bfd0b68cecc..b7c132bded7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -294,7 +294,11 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po | |||
| 294 | 294 | ||
| 295 | /* Ericsson products */ | 295 | /* Ericsson products */ |
| 296 | #define ERICSSON_VENDOR_ID 0x0bdb | 296 | #define ERICSSON_VENDOR_ID 0x0bdb |
| 297 | #define ERICSSON_PRODUCT_F3507G 0x1900 | 297 | #define ERICSSON_PRODUCT_F3507G_1 0x1900 |
| 298 | #define ERICSSON_PRODUCT_F3507G_2 0x1902 | ||
| 299 | |||
| 300 | #define BENQ_VENDOR_ID 0x04a5 | ||
| 301 | #define BENQ_PRODUCT_H10 0x4068 | ||
| 298 | 302 | ||
| 299 | static struct usb_device_id option_ids[] = { | 303 | static struct usb_device_id option_ids[] = { |
| 300 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, | 304 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, |
| @@ -509,7 +513,10 @@ static struct usb_device_id option_ids[] = { | |||
| 509 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, | 513 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, |
| 510 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, | 514 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, |
| 511 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, | 515 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, |
| 512 | { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) }, | 516 | { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) }, |
| 517 | { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) }, | ||
| 518 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, | ||
| 519 | { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ | ||
| 513 | { } /* Terminating entry */ | 520 | { } /* Terminating entry */ |
| 514 | }; | 521 | }; |
| 515 | MODULE_DEVICE_TABLE(usb, option_ids); | 522 | MODULE_DEVICE_TABLE(usb, option_ids); |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 50dc33a6065..6f59c8e510e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -907,13 +907,13 @@ UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, | |||
| 907 | "Genesys Logic", | 907 | "Genesys Logic", |
| 908 | "USB to IDE Optical", | 908 | "USB to IDE Optical", |
| 909 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 909 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 910 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), | 910 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), |
| 911 | 911 | ||
| 912 | UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, | 912 | UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, |
| 913 | "Genesys Logic", | 913 | "Genesys Logic", |
| 914 | "USB to IDE Disk", | 914 | "USB to IDE Disk", |
| 915 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 915 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 916 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), | 916 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), |
| 917 | 917 | ||
| 918 | /* Reported by Ben Efros <ben@pc-doctor.com> */ | 918 | /* Reported by Ben Efros <ben@pc-doctor.com> */ |
| 919 | UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, | 919 | UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 48ff701d3a7..2552b9f325e 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -2230,7 +2230,7 @@ static int __devexit pxafb_remove(struct platform_device *dev) | |||
| 2230 | 2230 | ||
| 2231 | static struct platform_driver pxafb_driver = { | 2231 | static struct platform_driver pxafb_driver = { |
| 2232 | .probe = pxafb_probe, | 2232 | .probe = pxafb_probe, |
| 2233 | .remove = pxafb_remove, | 2233 | .remove = __devexit_p(pxafb_remove), |
| 2234 | .suspend = pxafb_suspend, | 2234 | .suspend = pxafb_suspend, |
| 2235 | .resume = pxafb_resume, | 2235 | .resume = pxafb_resume, |
| 2236 | .driver = { | 2236 | .driver = { |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 8d0b1fb1e52..1f51366417b 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
| @@ -16,6 +16,12 @@ config W1_SLAVE_SMEM | |||
| 16 | Say Y here if you want to connect 1-wire | 16 | Say Y here if you want to connect 1-wire |
| 17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. | 17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. |
| 18 | 18 | ||
| 19 | config W1_SLAVE_DS2431 | ||
| 20 | tristate "1kb EEPROM family support (DS2431)" | ||
| 21 | help | ||
| 22 | Say Y here if you want to use a 1-wire | ||
| 23 | 1kb EEPROM family device (DS2431) | ||
| 24 | |||
| 19 | config W1_SLAVE_DS2433 | 25 | config W1_SLAVE_DS2433 |
| 20 | tristate "4kb EEPROM family support (DS2433)" | 26 | tristate "4kb EEPROM family support (DS2433)" |
| 21 | help | 27 | help |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index 990f400b6d2..f1f51f19b12 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | 5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o |
| 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
| 7 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o | ||
| 7 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
| 8 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 9 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
| 9 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | 10 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o |
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 858c16a544c..13944714882 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c | |||
| @@ -156,6 +156,9 @@ out_up: | |||
| 156 | */ | 156 | */ |
| 157 | static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) | 157 | static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) |
| 158 | { | 158 | { |
| 159 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC | ||
| 160 | struct w1_f23_data *f23 = sl->family_data; | ||
| 161 | #endif | ||
| 159 | u8 wrbuf[4]; | 162 | u8 wrbuf[4]; |
| 160 | u8 rdbuf[W1_PAGE_SIZE + 3]; | 163 | u8 rdbuf[W1_PAGE_SIZE + 3]; |
| 161 | u8 es = (addr + len - 1) & 0x1f; | 164 | u8 es = (addr + len - 1) & 0x1f; |
| @@ -196,7 +199,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) | |||
| 196 | 199 | ||
| 197 | /* Reset the bus to wake up the EEPROM (this may not be needed) */ | 200 | /* Reset the bus to wake up the EEPROM (this may not be needed) */ |
| 198 | w1_reset_bus(sl->master); | 201 | w1_reset_bus(sl->master); |
| 199 | 202 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC | |
| 203 | f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS)); | ||
| 204 | #endif | ||
| 200 | return 0; | 205 | return 0; |
| 201 | } | 206 | } |
| 202 | 207 | ||
