A few quick comments below...
On 11/17/2015 11:20 AM, [email protected] wrote:
> From: Wen Xiong <[email protected]>
>
> ---
> drivers/scsi/ipr.c | 157
> +++++++++++++++++++++++++++++++++++++++++++++++++++-
> drivers/scsi/ipr.h | 3 +
> 2 files changed, 159 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
> index 1248d27..3ae9ead 100644
> --- a/drivers/scsi/ipr.c
> +++ b/drivers/scsi/ipr.c
> @@ -102,6 +102,8 @@ static unsigned int ipr_number_of_msix = 2;
> static unsigned int ipr_fast_reboot;
> static unsigned int ipr_cpu_map = 0;
> static unsigned int ipr_use_blk_mq = 0;
> +static unsigned int ipr_poll_mode = 0;
> +static unsigned int ipr_poll_timer = 10;
>
> static unsigned int *ipr_used_cpu;
> static unsigned int ipr_possible_cpu_cnt;
> @@ -234,7 +236,10 @@ module_param_named(cpu_map, ipr_cpu_map, int, 0);
> MODULE_PARM_DESC(cpu_map, "Defines how to map CPUs to IRQ vectors per
> adapter");
> module_param_named(use_blk_mq, ipr_use_blk_mq, uint, S_IRUGO);
> MODULE_PARM_DESC(use_blk_mq, "ipr use block mq enable/disable. (default:
> disable(0))");
> -
> +module_param_named(poll_mode, ipr_poll_mode, uint, S_IRUGO);
> +MODULE_PARM_DESC(poll_mode, "ipr polling mode enable/disable. (default:
> disable(0))");
> +module_param_named(poll_timer, ipr_poll_timer, uint, S_IRUGO);
> +MODULE_PARM_DESC(poll_timer, "Milliseconds between polling. (default: 10)");
> MODULE_LICENSE("GPL");
> MODULE_VERSION(IPR_DRIVER_VERSION);
>
> @@ -3749,6 +3754,69 @@ static struct device_attribute ipr_iopoll_weight_attr
> = {
> };
>
> /**
> + * ipr_show_poll_mode - Show ipr polling mode
> + * @dev: class device struct
> + * @buf: buffer
> + *
> + * Return value:
> + * number of bytes printed to buffer
> + **/
> +static ssize_t ipr_show_poll_mode(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct Scsi_Host *shost = class_to_shost(dev);
> + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
> + unsigned long lock_flags = 0;
> + int len;
> +
> + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
> + len = snprintf(buf, PAGE_SIZE, "%d\n", ioa_cfg->poll_mode);
> + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
> + return len;
> +}
> +
> +static void ipr_disable_hrrq_interrupt(struct ipr_ioa_cfg *ioa_cfg);
> +/**
> + * ipr_store_poll_mode - Change the adapter's polling mode
> + * @dev: class device struct
> + * @buf: buffer
> + *
> + * Return value:
> + * number of bytes printed to buffer
> + **/
> +static ssize_t ipr_store_poll_mode(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct Scsi_Host *shost = class_to_shost(dev);
> + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
> + unsigned long lock_flags;
> + int i;
> +
> + if (kstrtoul(buf, 10, &ioa_cfg->poll_mode))
> + return -EINVAL;
> +
> + if (ioa_cfg->poll_mode && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
> + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
> + ipr_disable_hrrq_interrupt(ioa_cfg);
> + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
> + for (i = 0; i < IPR_MAX_HRRQ_NUM; i++)
> + add_timer(&ioa_cfg->hrrq[i].hrrq_poll_timer);
Should we perhaps use add_timer_on so the timer fires on the same core as the
HRRQ is
bound to?
> + }
> +
> + return strlen(buf);
> +}
> +
> +static struct device_attribute ipr_poll_mode_attr = {
> + .attr = {
> + .name = "poll_mode",
> + .mode = S_IRUGO | S_IWUSR,
> + },
> + .show = ipr_show_poll_mode,
> + .store = ipr_store_poll_mode
> +};
> +
> +/**
> * ipr_alloc_ucode_buffer - Allocates a microcode download buffer
> * @buf_len: buffer length
> *
> @@ -4190,6 +4258,7 @@ static struct device_attribute *ipr_ioa_attrs[] = {
> &ipr_ioa_fw_type_attr,
> &ipr_iopoll_weight_attr,
> &ipr_cpu_map_attr,
> + &ipr_poll_mode_attr,
> NULL,
> };
>
> @@ -5597,6 +5666,47 @@ static irqreturn_t ipr_handle_other_interrupt(struct
> ipr_ioa_cfg *ioa_cfg,
> }
>
> /**
> + * ipr_disable_hrrq_interrupt - Disable HRRQ interrupt
> + * @ioa_cfg pointer to ioa config struct
> + *
> +**/
> +static void ipr_disable_hrrq_interrupt(struct ipr_ioa_cfg *ioa_cfg)
> +{
> + u32 int_reg;
> +
> + /* Mask HRRQ interrupt */
> + if (ioa_cfg->sis64)
> + writeq(IPR_PCII_HRRQ_UPDATED,
> + ioa_cfg->regs.set_interrupt_mask_reg);
Seems like a bug if we call this function for SIS-32. I'm find not supporting
polling
mode for SIS-32, but let's remove this if check and just comment that this is
SIS-64 only.
> +
> + /* MMIO read to flush the write */
> + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
> +}
> +
> +/**
> + * ipr_enable_hrrq_interrupt - Enable HRRQ interrupt
> + * @ioa_cfg pointer to ioa config struct
> + *
> + **/
> +static void ipr_enable_hrrq_interrupt(struct ipr_ioa_cfg *ioa_cfg)
> +{
> + u32 int_reg;
> + int i;
> +
> + for (i = 0; i < IPR_MAX_HRRQ_NUM; i++)
> + if (!ioa_cfg->hrrq[i].allow_interrupts)
> + return;
> +
> + /* Enable HRRQ interrupt */
> + if (ioa_cfg->sis64)
> + writeq(IPR_PCII_HRRQ_UPDATED,
> + ioa_cfg->regs.clr_interrupt_mask_reg);
Same comment here as above.
> +
> + /* MMIO read to flush the write */
> + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
> +}
> +
> +/**
> * ipr_isr_eh - Interrupt service routine error handler
> * @ioa_cfg: ioa config struct
> * @msg: message to log
> @@ -5692,6 +5802,29 @@ static int ipr_iopoll(struct blk_iopoll *iop, int
> budget)
> return completed_ops;
> }
>
> +void ipr_hrrq_poll_timeout(unsigned long ptr)
Should be static
> +{
> + struct ipr_hrr_queue *hrrq = (struct ipr_hrr_queue *) ptr;
> + struct ipr_ioa_cfg *ioa_cfg = hrrq->ioa_cfg;
> + struct ipr_cmnd *ipr_cmd, *temp;
> + unsigned long hrrq_flags;
> + LIST_HEAD(doneq);
> +
> + if (ioa_cfg->poll_mode && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
> + spin_lock_irqsave(hrrq->lock, hrrq_flags);
> + ipr_process_hrrq(hrrq, -1, &doneq);
> + spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
> +
> + list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
> + list_del(&ipr_cmd->queue);
> + del_timer(&ipr_cmd->timer);
> + ipr_cmd->fast_done(ipr_cmd);
> + }
> + mod_timer(&hrrq->hrrq_poll_timer,
> + (jiffies + msecs_to_jiffies(ipr_poll_timer)));
> + }
> +}
> +
> /**
> * ipr_isr - Interrupt service routine
> * @irq: irq number
> @@ -9880,6 +10013,11 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg
> *ioa_cfg,
> ioa_cfg->hrrq[i].lock = ioa_cfg->host->host_lock;
> else
> ioa_cfg->hrrq[i].lock = &ioa_cfg->hrrq[i]._lock;
> +
> + init_timer(&ioa_cfg->hrrq[i].hrrq_poll_timer);
> + ioa_cfg->hrrq[i].hrrq_poll_timer.function =
> ipr_hrrq_poll_timeout;
> + ioa_cfg->hrrq[i].hrrq_poll_timer.data = (unsigned long)
> &ioa_cfg->hrrq[i];
> + ioa_cfg->hrrq[i].hrrq_poll_timer.expires = jiffies +
> msecs_to_jiffies(ipr_poll_timer);
> }
> }
>
> @@ -10547,6 +10685,12 @@ static void __ipr_remove(struct pci_dev *pdev)
>
> ipr_free_all_resources(ioa_cfg);
>
> + if (ioa_cfg->poll_mode && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
> + for (i = 0; i < IPR_MAX_HRRQ_NUM; i++)
> + del_timer(&ioa_cfg->hrrq[i].hrrq_poll_timer);
> + ipr_enable_hrrq_interrupt(ioa_cfg);
> + }
> +
> LEAVE;
> }
>
> @@ -10585,6 +10729,7 @@ static void ipr_remove(struct pci_dev *pdev)
> static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id
> *dev_id)
> {
> struct ipr_ioa_cfg *ioa_cfg;
> + unsigned long lock_flags = 0;
> int rc, i;
>
> rc = ipr_probe_ioa(pdev, dev_id);
> @@ -10630,6 +10775,7 @@ static int ipr_probe(struct pci_dev *pdev, const
> struct pci_device_id *dev_id)
> scsi_scan_host(ioa_cfg->host);
> ioa_cfg->iopoll_weight = ioa_cfg->chip_cfg->iopoll_weight;
> ioa_cfg->use_blk_mq = ipr_use_blk_mq;
> + ioa_cfg->poll_mode = ipr_poll_mode;
>
> if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
> for (i = 1; i < ioa_cfg->hrrq_num; i++) {
> @@ -10639,6 +10785,15 @@ static int ipr_probe(struct pci_dev *pdev, const
> struct pci_device_id *dev_id)
> }
> }
>
> + if (ioa_cfg->poll_mode && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
> + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
> + ipr_disable_hrrq_interrupt(ioa_cfg);
> + for (i = 0; i < ioa_cfg->hrrq_num; i++)
> + add_timer(&ioa_cfg->hrrq[i].hrrq_poll_timer);
Same comment as above regarding using add_timer_on
> +
> + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
> + }
> +
> schedule_work(&ioa_cfg->work_q);
> return 0;
> }
> diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
> index c28a673..caa747c 100644
> --- a/drivers/scsi/ipr.h
> +++ b/drivers/scsi/ipr.h
> @@ -518,6 +518,7 @@ struct ipr_hrr_queue {
> u8 removing_ioa:1;
>
> struct blk_iopoll iopoll;
> + struct timer_list hrrq_poll_timer;
> };
>
> /* Command packet structure */
> @@ -1612,6 +1613,8 @@ struct ipr_ioa_cfg {
>
> u32 use_blk_mq;
>
> + u32 poll_mode;
> +
> }; /* struct ipr_ioa_cfg */
>
> struct ipr_cmnd {
>
--
Brian King
Power Linux I/O
IBM Linux Technology Center
------------------------------------------------------------------------------
Give your users amazing mobile app experiences with Intel XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2-D/3-D games for multiple OSs.
Then get your creation into app stores sooner, with many ways to monetize.
http://pubads.g.doubleclick.net/gampad/clk?id=254741551&iu=/4140
_______________________________________________
Iprdd-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/iprdd-devel