diff options
Diffstat (limited to 'drivers')
98 files changed, 3803 insertions, 371 deletions
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 63719ab9ea44..115b1cd6dcf5 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 f1bb2f9fecbf..b05b86a912c5 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 6c1d778b63a9..e3bc1b436284 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 4ae1a4138b47..7007edd2d451 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/block/cciss.c b/drivers/block/cciss.c index d2cb67b61176..b5a061114630 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -3611,11 +3611,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3611 | schedule_timeout_uninterruptible(30*HZ); | 3611 | schedule_timeout_uninterruptible(30*HZ); |
| 3612 | 3612 | ||
| 3613 | /* Now try to get the controller to respond to a no-op */ | 3613 | /* Now try to get the controller to respond to a no-op */ |
| 3614 | for (i=0; i<12; i++) { | 3614 | for (i=0; i<30; i++) { |
| 3615 | if (cciss_noop(pdev) == 0) | 3615 | if (cciss_noop(pdev) == 0) |
| 3616 | break; | 3616 | break; |
| 3617 | else | 3617 | |
| 3618 | printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : "")); | 3618 | schedule_timeout_uninterruptible(HZ); |
| 3619 | } | ||
| 3620 | if (i == 30) { | ||
| 3621 | printk(KERN_ERR "cciss: controller seems dead\n"); | ||
| 3622 | return -EBUSY; | ||
| 3619 | } | 3623 | } |
| 3620 | } | 3624 | } |
| 3621 | 3625 | ||
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 918ef725de41..b6c8ce254359 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); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 733028b4d45e..1c3a8c557140 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 5a4d3244758a..a839a28d8ee6 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_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50c..93e677a481f5 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/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2d797ffe8137..6dab63bdc4c1 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_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 28b726d07a0c..85685bfd12da 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -3548,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 3548 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 3548 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
| 3549 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | 3549 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; |
| 3550 | 3550 | ||
| 3551 | DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); | 3551 | DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); |
| 3552 | ret = copy_from_user(obj_addr, user_data, args->size); | 3552 | ret = copy_from_user(obj_addr, user_data, args->size); |
| 3553 | if (ret) | 3553 | if (ret) |
| 3554 | return -EFAULT; | 3554 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 65be30dccc77..fc28e2bbd542 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 65b635ce28c8..a2834276cb38 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 9fee3ca17344..9aefb5e5864d 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 edab51973bf5..a7c59908c457 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 8e8467970481..c016f7a2c5fc 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-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 6af68146c342..bdb1f7510e91 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 162b74a04886..42df0eca43d5 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 b1c9abe24c7b..e7d984866de0 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 c171988a9f51..7e13d2df9af3 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 3dad2299d9c5..e072903b12f0 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 | ||
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 69660a431cd9..77267c859965 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/atiixp.c b/drivers/ide/atiixp.c index b2735d28f5cc..ecd1e62ca91a 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 0bfeb0c79d6e..ddfbea41d296 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 ac40d6cb90a2..c878bfcf1116 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-gd.c b/drivers/ide/ide-gd.c index 7857b209c6df..047109419902 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 a86779f0756b..b604bdd318a1 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-tape.c b/drivers/ide/ide-tape.c index d7ecd3c79757..bb450a7608c2 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 | } |
| @@ -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 258805da15c3..0920e3b0c962 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 e1c4f5437396..13b8153112ed 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 2727bcd24194..467373cab8e5 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 2beb8d94f7bd..872338003721 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 10c3d9f8c038..675b3135d5f1 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 d2d5bc3546d7..20b693be14b2 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 b5de5f21ef78..c2089c093aa7 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 906c5a98d814..53aada5bbe1e 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 15ea09733e84..ee5acdbd114a 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/md/raid1.c b/drivers/md/raid1.c index 01e3cffd03b8..e2466425d9ca 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 6736d6dff981..7301631abe04 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 40ebde53b3ce..b0198691892a 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 f91e9eb15e52..6092a5bb5a7d 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 b386cc66c6b3..451974ba32f3 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 5b30dfc7846b..76e37fd96bb6 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 676413a915b4..91068952b502 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 000000000000..69028253e984 --- /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 000000000000..2034695ba194 --- /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 000000000000..4e207658c5d9 --- /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 000000000000..b55d9ccaf33e --- /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 000000000000..eeb80d0ea3ff --- /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 000000000000..9d308dd32a5c --- /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 000000000000..7ba43630a25d --- /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 000000000000..46a6324d7b73 --- /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 000000000000..d48530b81e61 --- /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 5d882a44e3ee..2ac738fa6a07 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 a1d6008efcbb..07c334f25aae 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 9a2586b07a05..ddcb81d0b81a 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/misc/hpilo.c b/drivers/misc/hpilo.c index f26667a7abf7..cf991850f01b 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/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 821d0ed6bae3..c76d6e5f47ee 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 a425d09f35a0..00248e81ecd5 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 acd4ea9b2278..5a401d8047ab 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 0225cbbf22de..043d50fb6ef6 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 6fec86aaed7e..576611f605db 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 5f7a245ed132..424f17d6ffd1 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 87743661d48e..4b122e7ab4b3 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/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b0ee86c62685..ab13ff22a8c0 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/pci/dmar.c b/drivers/pci/dmar.c index f5a662a50acb..26c536b51c5a 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 db85284ffb62..39ae37589fda 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 c2485542f543..681e3912b821 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 71a8012886b0..7a16c6897bb9 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 f78371b22529..45effc5726c0 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 aac7006949f1..d0c973685868 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 f9b874eaeb9f..248b4db91552 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 baad093aafe3..f20d55368edb 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/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b9766..022e89ffec1d 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 ab69c1bf36a8..c2747bc88c6f 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 79c225acd1ad..f636296b54bc 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 af64cfbe16db..7370296225e1 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 94534955e38b..66de5cc8ddf1 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 b003f9a7e151..f716b2e92b65 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 326dd7f65ee9..b3d5a23ab56f 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 31fb204f44c6..49e7f56e0d7f 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 3219d137340a..e55fef52a5dc 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 80c2e7e9622f..38aa896cc5db 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 b10fa31cc915..1ab9dac7e12d 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 f3c6703cffda..d8d9a52a44b3 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 4725d15d096f..e551bb38852b 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 0431397836f6..10d52919abbb 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 a081ee65bde6..07bcb931021b 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 fb7054ccf4fc..262b00c9b334 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 5a8fd5d57a11..2dc7606f319c 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 2cc34fa05b73..af77e4659006 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 4ea305387981..c7ebd0867fcc 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 a035ceccf950..6dbbd0786a6a 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 bfd0b68ceccd..b7c132bded7f 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 50dc33a6065b..6f59c8e510ea 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/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 8d0b1fb1e52e..1f51366417b9 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 990f400b6d22..f1f51f19b129 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 858c16a544c2..139447148822 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 | ||
