Lines Matching +full:channel +full:- +full:fifo +full:- +full:len
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
52 static inline int mk_entry(int id, int len) in mk_entry() argument
54 int qlen = len & 7 ? (len >> 3) + 1 : len >> 3; in mk_entry()
64 * FIFO queues, shared with hardware.
75 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); in fifo_enqueue()
79 spin_lock_irqsave(&hw->fifo_lock, flags); in fifo_enqueue()
80 if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask] in fifo_enqueue()
82 fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |= in fifo_enqueue()
83 (entry & ENTRY_MASK_NOSTATE) | fifo_q->merge; in fifo_enqueue()
84 fifo_q->tail += 1; in fifo_enqueue()
87 spin_unlock_irqrestore(&hw->fifo_lock, flags); in fifo_enqueue()
94 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); in fifo_dequeue()
99 spin_lock_irqsave(&hw->fifo_lock, flags); in fifo_dequeue()
100 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask]; in fifo_dequeue()
105 fifo_q->fifobar[fifo_q->head & fifo_q->imask] = in fifo_dequeue()
107 fifo_q->head += 1; in fifo_dequeue()
110 spin_unlock_irqrestore(&hw->fifo_lock, flags); in fifo_dequeue()
117 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); in fifo_check_recv()
122 spin_lock_irqsave(&hw->fifo_lock, flags); in fifo_check_recv()
123 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask]; in fifo_check_recv()
126 spin_unlock_irqrestore(&hw->fifo_lock, flags); in fifo_check_recv()
132 int dir, int id, int len) in ilo_pkt_enqueue() argument
138 fifobar = ccb->ccb_u1.send_fifobar; in ilo_pkt_enqueue()
140 fifobar = ccb->ccb_u3.recv_fifobar; in ilo_pkt_enqueue()
142 entry = mk_entry(id, len); in ilo_pkt_enqueue()
147 int dir, int *id, int *len, void **pkt) in ilo_pkt_dequeue() argument
154 fifobar = ccb->ccb_u1.send_fifobar; in ilo_pkt_dequeue()
155 desc = ccb->ccb_u2.send_desc; in ilo_pkt_dequeue()
157 fifobar = ccb->ccb_u3.recv_fifobar; in ilo_pkt_dequeue()
158 desc = ccb->ccb_u4.recv_desc; in ilo_pkt_dequeue()
166 if (len) in ilo_pkt_dequeue()
167 *len = get_entry_len(entry); in ilo_pkt_dequeue()
177 char *fifobar = ccb->ccb_u3.recv_fifobar; in ilo_pkt_recv()
184 iowrite8(1, ccb->ccb_u5.db_base); in doorbell_set()
189 iowrite8(2, ccb->ccb_u5.db_base); in doorbell_clr()
205 ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1); in ctrl_setup()
206 ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1); in ctrl_setup()
211 /* size of a fifo is determined by the number of entries it contains */ in fifo_sz()
217 struct fifo *fifo_q = base_addr; in fifo_setup()
220 /* set up an empty fifo */ in fifo_setup()
221 fifo_q->head = 0; in fifo_setup()
222 fifo_q->tail = 0; in fifo_setup()
223 fifo_q->reset = 0; in fifo_setup()
224 fifo_q->nrents = nr_entry; in fifo_setup()
225 fifo_q->imask = nr_entry - 1; in fifo_setup()
226 fifo_q->merge = ENTRY_MASK_O; in fifo_setup()
229 fifo_q->fifobar[i] = 0; in fifo_setup()
234 struct ccb *driver_ccb = &data->driver_ccb; in ilo_ccb_close()
235 struct ccb __iomem *device_ccb = data->mapped_ccb; in ilo_ccb_close()
240 iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), in ilo_ccb_close()
241 &device_ccb->send_ctrl); in ilo_ccb_close()
242 iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G), in ilo_ccb_close()
243 &device_ccb->recv_ctrl); in ilo_ccb_close()
246 for (retries = MAX_WAIT; retries > 0; retries--) { in ilo_ccb_close()
249 if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) in ilo_ccb_close()
251 !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) in ilo_ccb_close()
255 dev_err(&pdev->dev, "Closing, but controller still active\n"); in ilo_ccb_close()
261 dma_free_coherent(&pdev->dev, data->dma_size, data->dma_va, in ilo_ccb_close()
262 data->dma_pa); in ilo_ccb_close()
271 driver_ccb = &data->driver_ccb; in ilo_ccb_setup()
272 ilo_ccb = &data->ilo_ccb; in ilo_ccb_setup()
274 data->dma_size = 2 * fifo_sz(NR_QENTRY) + in ilo_ccb_setup()
278 data->dma_va = dma_alloc_coherent(&hw->ilo_dev->dev, data->dma_size, in ilo_ccb_setup()
279 &data->dma_pa, GFP_ATOMIC); in ilo_ccb_setup()
280 if (!data->dma_va) in ilo_ccb_setup()
281 return -ENOMEM; in ilo_ccb_setup()
283 dma_va = (char *)data->dma_va; in ilo_ccb_setup()
284 dma_pa = data->dma_pa; in ilo_ccb_setup()
297 driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE; in ilo_ccb_setup()
298 ilo_ccb->ccb_u1.send_fifobar_pa = dma_pa + FIFOHANDLESIZE; in ilo_ccb_setup()
306 driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE; in ilo_ccb_setup()
307 ilo_ccb->ccb_u3.recv_fifobar_pa = dma_pa + FIFOHANDLESIZE; in ilo_ccb_setup()
311 driver_ccb->ccb_u2.send_desc = dma_va; in ilo_ccb_setup()
312 ilo_ccb->ccb_u2.send_desc_pa = dma_pa; in ilo_ccb_setup()
316 driver_ccb->ccb_u4.recv_desc = dma_va; in ilo_ccb_setup()
317 ilo_ccb->ccb_u4.recv_desc_pa = dma_pa; in ilo_ccb_setup()
319 driver_ccb->channel = slot; in ilo_ccb_setup()
320 ilo_ccb->channel = slot; in ilo_ccb_setup()
322 driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE); in ilo_ccb_setup()
323 ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */ in ilo_ccb_setup()
331 struct ccb *driver_ccb = &data->driver_ccb; in ilo_ccb_open()
334 data->mapped_ccb = (struct ccb __iomem *) in ilo_ccb_open()
335 (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); in ilo_ccb_open()
336 memcpy_toio(data->mapped_ccb, &data->ilo_ccb, sizeof(struct ccb)); in ilo_ccb_open()
356 struct ccb *driver_ccb = &data->driver_ccb; in ilo_ccb_verify()
359 for (i = MAX_WAIT; i > 0; i--) { in ilo_ccb_verify()
366 dev_err(&hw->ilo_dev->dev, "Open could not dequeue a packet\n"); in ilo_ccb_verify()
367 return -EBUSY; in ilo_ccb_verify()
377 /* check for this particular channel needing a reset */ in is_channel_reset()
378 return FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset; in is_channel_reset()
383 /* set a flag indicating this channel needs a reset */ in set_channel_reset()
384 FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1; in set_channel_reset()
389 return ioread32(&hw->mmio_vaddr[DB_OUT]); in get_device_outbound()
399 iowrite32(clr, &hw->mmio_vaddr[DB_OUT]); in clear_pending_db()
404 /* clear the device (reset bits, pending channel entries) */ in clear_device()
405 clear_pending_db(hw, -1); in clear_device()
410 iowrite8(ioread8(&hw->mmio_vaddr[DB_IRQ]) | 1, &hw->mmio_vaddr[DB_IRQ]); in ilo_enable_interrupts()
415 iowrite8(ioread8(&hw->mmio_vaddr[DB_IRQ]) & ~1, in ilo_disable_interrupts()
416 &hw->mmio_vaddr[DB_IRQ]); in ilo_disable_interrupts()
428 if (!hw->ccb_alloc[slot]) in ilo_set_reset()
430 set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb); in ilo_set_reset()
435 size_t len, loff_t *off) in ilo_read() argument
438 struct ccb_data *data = fp->private_data; in ilo_read()
439 struct ccb *driver_ccb = &data->driver_ccb; in ilo_read()
440 struct ilo_hwinfo *hw = data->ilo_hw; in ilo_read()
448 return -ENODEV; in ilo_read()
453 * in the channel, and will return an error if no packet is found in ilo_read()
465 cnt--; in ilo_read()
470 return -EAGAIN; in ilo_read()
473 if (pkt_len < len) in ilo_read()
474 len = pkt_len; in ilo_read()
476 err = copy_to_user(buf, pkt, len); in ilo_read()
481 return err ? -EFAULT : len; in ilo_read()
485 size_t len, loff_t *off) in ilo_write() argument
488 struct ccb_data *data = fp->private_data; in ilo_write()
489 struct ccb *driver_ccb = &data->driver_ccb; in ilo_write()
490 struct ilo_hwinfo *hw = data->ilo_hw; in ilo_write()
494 return -ENODEV; in ilo_write()
498 return -EBUSY; in ilo_write()
501 if (pkt_len < len) in ilo_write()
502 len = pkt_len; in ilo_write()
504 /* on failure, set the len to 0 to return empty packet to the device */ in ilo_write()
505 err = copy_from_user(pkt, buf, len); in ilo_write()
507 len = 0; in ilo_write()
510 ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len); in ilo_write()
513 return err ? -EFAULT : len; in ilo_write()
518 struct ccb_data *data = fp->private_data; in ilo_poll()
519 struct ccb *driver_ccb = &data->driver_ccb; in ilo_poll()
521 poll_wait(fp, &data->ccb_waitq, wait); in ilo_poll()
525 else if (ilo_pkt_recv(data->ilo_hw, driver_ccb)) in ilo_poll()
539 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); in ilo_close()
541 spin_lock(&hw->open_lock); in ilo_close()
543 if (hw->ccb_alloc[slot]->ccb_cnt == 1) { in ilo_close()
545 data = fp->private_data; in ilo_close()
547 spin_lock_irqsave(&hw->alloc_lock, flags); in ilo_close()
548 hw->ccb_alloc[slot] = NULL; in ilo_close()
549 spin_unlock_irqrestore(&hw->alloc_lock, flags); in ilo_close()
551 ilo_ccb_close(hw->ilo_dev, data); in ilo_close()
555 hw->ccb_alloc[slot]->ccb_cnt--; in ilo_close()
557 spin_unlock(&hw->open_lock); in ilo_close()
570 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); in ilo_open()
575 return -ENOMEM; in ilo_open()
577 spin_lock(&hw->open_lock); in ilo_open()
580 if (hw->ccb_alloc[slot] == NULL) { in ilo_open()
581 /* create a channel control block for this minor */ in ilo_open()
588 data->ccb_cnt = 1; in ilo_open()
589 data->ccb_excl = fp->f_flags & O_EXCL; in ilo_open()
590 data->ilo_hw = hw; in ilo_open()
591 init_waitqueue_head(&data->ccb_waitq); in ilo_open()
594 spin_lock_irqsave(&hw->alloc_lock, flags); in ilo_open()
596 hw->ccb_alloc[slot] = data; in ilo_open()
597 spin_unlock_irqrestore(&hw->alloc_lock, flags); in ilo_open()
599 /* make sure the channel is functional */ in ilo_open()
603 spin_lock_irqsave(&hw->alloc_lock, flags); in ilo_open()
604 hw->ccb_alloc[slot] = NULL; in ilo_open()
605 spin_unlock_irqrestore(&hw->alloc_lock, flags); in ilo_open()
607 ilo_ccb_close(hw->ilo_dev, data); in ilo_open()
615 if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) { in ilo_open()
617 * The channel exists, and either this open in ilo_open()
618 * or a previous open of this channel wants in ilo_open()
621 error = -EBUSY; in ilo_open()
623 hw->ccb_alloc[slot]->ccb_cnt++; in ilo_open()
628 spin_unlock(&hw->open_lock); in ilo_open()
631 fp->private_data = hw->ccb_alloc[slot]; in ilo_open()
651 spin_lock(&hw->alloc_lock); in ilo_isr()
656 spin_unlock(&hw->alloc_lock); in ilo_isr()
662 pending = -1; in ilo_isr()
667 if (!hw->ccb_alloc[i]) in ilo_isr()
670 wake_up_interruptible(&hw->ccb_alloc[i]->ccb_waitq); in ilo_isr()
676 spin_unlock(&hw->alloc_lock); in ilo_isr()
683 pci_iounmap(pdev, hw->db_vaddr); in ilo_unmap_device()
684 pci_iounmap(pdev, hw->ram_vaddr); in ilo_unmap_device()
685 pci_iounmap(pdev, hw->mmio_vaddr); in ilo_unmap_device()
696 hw->mmio_vaddr = pci_iomap(pdev, 1, 0); in ilo_map_device()
697 if (hw->mmio_vaddr == NULL) { in ilo_map_device()
698 dev_err(&pdev->dev, "Error mapping mmio\n"); in ilo_map_device()
705 dev_err(&pdev->dev, "Error reading PCI rev id: %d\n", rc); in ilo_map_device()
712 off = pci_resource_len(pdev, bar) - 0x2000; in ilo_map_device()
717 hw->ram_vaddr = pci_iomap_range(pdev, bar, off, max_ccb * ILOHW_CCB_SZ); in ilo_map_device()
718 if (hw->ram_vaddr == NULL) { in ilo_map_device()
719 dev_err(&pdev->dev, "Error mapping shared mem\n"); in ilo_map_device()
724 hw->db_vaddr = pci_iomap(pdev, 3, max_ccb * ONE_DB_SIZE); in ilo_map_device()
725 if (hw->db_vaddr == NULL) { in ilo_map_device()
726 dev_err(&pdev->dev, "Error mapping doorbell\n"); in ilo_map_device()
732 pci_iounmap(pdev, hw->ram_vaddr); in ilo_map_device()
734 pci_iounmap(pdev, hw->mmio_vaddr); in ilo_map_device()
736 return -ENOMEM; in ilo_map_device()
749 minor = MINOR(ilo_hw->cdev.dev); in ilo_remove()
753 cdev_del(&ilo_hw->cdev); in ilo_remove()
755 free_irq(pdev->irq, ilo_hw); in ilo_remove()
777 dev_dbg(&pdev->dev, "Not supported on this device\n"); in ilo_probe()
778 return -ENODEV; in ilo_probe()
795 dev_err(&pdev->dev, "Error finding free device\n"); in ilo_probe()
796 return -ENODEV; in ilo_probe()
800 error = -ENOMEM; in ilo_probe()
805 ilo_hw->ilo_dev = pdev; in ilo_probe()
806 spin_lock_init(&ilo_hw->alloc_lock); in ilo_probe()
807 spin_lock_init(&ilo_hw->fifo_lock); in ilo_probe()
808 spin_lock_init(&ilo_hw->open_lock); in ilo_probe()
827 error = request_irq(pdev->irq, ilo_isr, IRQF_SHARED, "hpilo", ilo_hw); in ilo_probe()
833 cdev_init(&ilo_hw->cdev, &ilo_fops); in ilo_probe()
834 ilo_hw->cdev.owner = THIS_MODULE; in ilo_probe()
836 error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), max_ccb); in ilo_probe()
838 dev_err(&pdev->dev, "Could not add cdev\n"); in ilo_probe()
844 dev = device_create(&ilo_class, &pdev->dev, in ilo_probe()
848 dev_err(&pdev->dev, "Could not create files\n"); in ilo_probe()
854 free_irq(pdev->irq, ilo_hw); in ilo_probe()
924 MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8-24)(default=16)");