static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) { struct ccb *driver_ccb = &data->driver_ccb; struct ccb __iomem *device_ccb = data->mapped_ccb; int retries; /* complicated dance to tell the hw we are stopping */ doorbell_clr(driver_ccb); iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), &device_ccb->send_ctrl); iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G), &device_ccb->recv_ctrl); /* give iLO some time to process stop request */ for (retries = MAX_WAIT; retries > 0; retries--) { doorbell_set(driver_ccb); udelay(WAIT_TIME); if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) && !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) break; } if (retries == 0) dev_err(&pdev->dev, "Closing, but controller still active\n"); /* clear the hw ccb */ memset_io(device_ccb, 0, sizeof(struct ccb)); /* free resources used to back send/recv queues */ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); }
static ssize_t ilo_write(struct file *fp, const char __user *buf, size_t len, loff_t *off) { int err, pkt_id, pkt_len; struct ccb_data *data = fp->private_data; struct ccb *driver_ccb = &data->driver_ccb; struct ilo_hwinfo *hw = data->ilo_hw; void *pkt; if (is_channel_reset(driver_ccb)) return -ENODEV; /* get a packet to send the user command */ if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt)) return -EBUSY; /* limit the length to the length of the packet */ if (pkt_len < len) len = pkt_len; /* on failure, set the len to 0 to return empty packet to the device */ err = copy_from_user(pkt, buf, len); if (err) len = 0; /* send the packet */ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len); doorbell_set(driver_ccb); return err ? -EFAULT : len; }
static ssize_t ilo_write(struct file *fp, const char __user *buf, size_t len, loff_t *off) { int err, pkt_id, pkt_len; struct ccb_data *data = fp->private_data; struct ccb *driver_ccb = &data->driver_ccb; struct ilo_hwinfo *hw = data->ilo_hw; void *pkt; if (is_channel_reset(driver_ccb)) return -ENODEV; /* */ if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt)) return -EBUSY; /* */ if (pkt_len < len) len = pkt_len; /* */ err = copy_from_user(pkt, buf, len); if (err) len = 0; /* */ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len); doorbell_set(driver_ccb); return err ? -EFAULT : len; }
static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) { struct ccb *driver_ccb = &data->driver_ccb; struct ccb __iomem *device_ccb = data->mapped_ccb; int retries; /* */ doorbell_clr(driver_ccb); iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), &device_ccb->send_ctrl); iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G), &device_ccb->recv_ctrl); /* */ for (retries = MAX_WAIT; retries > 0; retries--) { doorbell_set(driver_ccb); udelay(WAIT_TIME); if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) && !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) break; } if (retries == 0) dev_err(&pdev->dev, "Closing, but controller still active\n"); /* */ memset_io(device_ccb, 0, sizeof(struct ccb)); /* */ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); }
static int ilo_ccb_verify(struct ilo_hwinfo *hw, struct ccb_data *data) { int pkt_id, i; struct ccb *driver_ccb = &data->driver_ccb; /* make sure iLO is really handling requests */ for (i = MAX_WAIT; i > 0; i--) { if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) break; udelay(WAIT_TIME); } if (i == 0) { dev_err(&hw->ilo_dev->dev, "Open could not dequeue a packet\n"); return -EBUSY; } ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0); doorbell_set(driver_ccb); return 0; }
static void ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) { int pkt_id, pkt_sz; struct ccb *driver_ccb = &data->driver_ccb; /* copy the ccb with physical addrs to device memory */ data->mapped_ccb = (struct ccb __iomem *) (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); memcpy_toio(data->mapped_ccb, &data->ilo_ccb, sizeof(struct ccb)); /* put packets on the send and receive queues */ pkt_sz = 0; for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) { ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz); doorbell_set(driver_ccb); } pkt_sz = desc_mem_sz(1); for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz); /* the ccb is ready to use */ doorbell_clr(driver_ccb); }
static void ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) { int pkt_id, pkt_sz; struct ccb *driver_ccb = &data->driver_ccb; /* */ data->mapped_ccb = (struct ccb __iomem *) (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); memcpy_toio(data->mapped_ccb, &data->ilo_ccb, sizeof(struct ccb)); /* */ pkt_sz = 0; for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) { ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz); doorbell_set(driver_ccb); } pkt_sz = desc_mem_sz(1); for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz); /* */ doorbell_clr(driver_ccb); }