Brian King <brk...@linux.vnet.ibm.com> writes:

> Removes the free and pending ipr_cmd queues. This is the first patch in a 
> series
> to make queuecommand lockless for the ipr driver. Creates a bitarray for each
> hardware queue so we can track whether an ipr_cmd struct is free or not. Also
> adds an atomic flag on each ipr_cmd to ensure we don't race between command
> completion and error handling.

Nice patch.  My main concern is whether we are duplicating functionality
from the upper layers.  I'm not familiar with scsi-mq, but isn't the
timeout/completion race handled by the blk-mq layer?  Also, can't the
active commands be handled by the tags bitmap?  I'm a bit puzzled by
this, would be nice if you can explain why we need this design in the
low-level driver.


>
> Signed-off-by: Brian King <brk...@linux.vnet.ibm.com>
> ---
>
>  drivers/scsi/ipr.c |  176 
> +++++++++++++++++++++--------------------------------
>  drivers/scsi/ipr.h |   51 ++++++++++++++-
>  2 files changed, 122 insertions(+), 105 deletions(-)
>
> diff -puN drivers/scsi/ipr.h~ipr_cmd_bitarray drivers/scsi/ipr.h
> --- linux-2.6.git/drivers/scsi/ipr.h~ipr_cmd_bitarray 2016-09-05 
> 14:44:02.353628212 -0500
> +++ linux-2.6.git-bjking1/drivers/scsi/ipr.h  2016-09-05 15:18:16.881117822 
> -0500
> @@ -507,9 +507,8 @@ struct ipr_hrr_queue {
>       volatile __be32 *hrrq_start;
>       volatile __be32 *hrrq_end;
>       volatile __be32 *hrrq_curr;
> +     unsigned long *active_map;
>
> -     struct list_head hrrq_free_q;
> -     struct list_head hrrq_pending_q;
>       struct list_head hrrq_error_q;
>       spinlock_t _lock;
>       spinlock_t *lock;
> @@ -1621,6 +1620,7 @@ struct ipr_cmnd {
>       struct list_head queue;
>       struct scsi_cmnd *scsi_cmd;
>       struct ata_queued_cmd *qc;
> +     unsigned long atomic_flags;
>       struct completion completion;
>       struct timer_list timer;
>       struct work_struct work;
> @@ -1847,6 +1847,53 @@ ipr_err("-------------------------------
>   * Inlines
>   */
>
> +enum ipr_atomic_flags {
> +     IPR_CMD_COMPLETE = 0,
> +};
> +
> +static inline int ipr_cmnd_complete(struct ipr_cmnd *ipr_cmd)
> +{
> +     /* xxx may be overkill since completions all occur under the HRRQ lock 
> */
> +     return test_and_set_bit(IPR_CMD_COMPLETE, &ipr_cmd->atomic_flags);

If we have to keep this handled in the ipr driver, I don't see this as
overkill.

> +}
> +
> +static inline void ipr_cmnd_clear_complete(struct ipr_cmnd *ipr_cmd)
> +{
> +     clear_bit(IPR_CMD_COMPLETE, &ipr_cmd->atomic_flags);
> +}
> +
> +static inline void ipr_free_cmd(struct ipr_cmnd *ipr_cmd)
> +{
> +     clear_bit(ipr_cmd->cmd_index - ipr_cmd->hrrq->min_cmd_id,
> +               ipr_cmd->hrrq->active_map);
> +}
> +
> +static inline struct ipr_cmnd* ipr_first_active_cmd(struct ipr_hrr_queue 
> *hrrq)
> +{
> +     int i = find_first_bit(hrrq->active_map, hrrq->size);
> +     struct ipr_cmnd *ipr_cmd = NULL;
> +
> +     if (i < hrrq->size)
> +             ipr_cmd = hrrq->ioa_cfg->ipr_cmnd_list[i + hrrq->min_cmd_id];
> +     return ipr_cmd;
> +}
> +
> +static inline struct ipr_cmnd* ipr_next_active_cmd(struct ipr_hrr_queue 
> *hrrq, struct ipr_cmnd *ipr_cmd)
> +{
> +     int last = ipr_cmd->cmd_index - hrrq->min_cmd_id;
> +     int i;
> +
> +     i = find_next_bit(hrrq->active_map, hrrq->size, last + 1);
> +     if (i < hrrq->size)
> +             return hrrq->ioa_cfg->ipr_cmnd_list[i + hrrq->min_cmd_id];
> +     return NULL;
> +}
> +
> +#define for_each_active_cmd(ipr_cmd, hrrq) \
> +             for (ipr_cmd = ipr_first_active_cmd(hrrq); \
> +                     ipr_cmd; \
> +                     ipr_cmd = ipr_next_active_cmd(hrrq, ipr_cmd))
> +
>  /**
>   * ipr_is_ioa_resource - Determine if a resource is the IOA
>   * @res:     resource entry struct
> diff -puN drivers/scsi/ipr.c~ipr_cmd_bitarray drivers/scsi/ipr.c
> --- linux-2.6.git/drivers/scsi/ipr.c~ipr_cmd_bitarray 2016-09-05 
> 14:44:02.357628190 -0500
> +++ linux-2.6.git-bjking1/drivers/scsi/ipr.c  2016-09-05 15:19:21.255759157 
> -0500
> @@ -656,6 +656,7 @@ static void ipr_reinit_ipr_cmnd(struct i
>       dma_addr_t dma_addr = ipr_cmd->dma_addr;
>       int hrrq_id;
>
> +     ipr_cmnd_clear_complete(ipr_cmd);
>       hrrq_id = ioarcb->cmd_pkt.hrrq_id;
>       memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
>       ioarcb->cmd_pkt.hrrq_id = hrrq_id;
> @@ -711,16 +712,17 @@ static void ipr_init_ipr_cmnd(struct ipr
>  static
>  struct ipr_cmnd *__ipr_get_free_ipr_cmnd(struct ipr_hrr_queue *hrrq)
>  {
> -     struct ipr_cmnd *ipr_cmd = NULL;
> +     int index;
>
> -     if (likely(!list_empty(&hrrq->hrrq_free_q))) {
> -             ipr_cmd = list_entry(hrrq->hrrq_free_q.next,
> -                     struct ipr_cmnd, queue);
> -             list_del(&ipr_cmd->queue);
> -     }
> +     do {
> +             index = find_first_zero_bit(hrrq->active_map, hrrq->size);
>
> +             if (index == hrrq->size)
> +                     return NULL;
>
> -     return ipr_cmd;
> +     } while (test_and_set_bit(index, hrrq->active_map));
> +
> +     return hrrq->ioa_cfg->ipr_cmnd_list[index + hrrq->min_cmd_id];
>  }
>
>  /**
> @@ -843,7 +845,7 @@ static void ipr_sata_eh_done(struct ipr_
>       sata_port->ioasa.status |= ATA_BUSY;
>
>       spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags);
>       ata_qc_complete(qc);
>  }
> @@ -869,7 +871,7 @@ static void __ipr_scsi_eh_done(struct ip
>       if (ipr_cmd->eh_comp)
>               complete(ipr_cmd->eh_comp);
>       spin_lock(&ipr_cmd->hrrq->_lock);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       spin_unlock(&ipr_cmd->hrrq->_lock);
>  }
>
> @@ -897,9 +899,6 @@ static void ipr_scsi_eh_done(struct ipr_
>       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
>       if (ipr_cmd->eh_comp)
>               complete(ipr_cmd->eh_comp);
> -     spin_lock(&ipr_cmd->hrrq->_lock);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> -     spin_unlock(&ipr_cmd->hrrq->_lock);
>       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
>  }
>
> @@ -937,27 +936,30 @@ static void ipr_send_back_failed_ops(str
>   **/
>  static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
>  {
> -     struct ipr_cmnd *ipr_cmd, *temp;
> +     struct ipr_cmnd *ipr_cmd;
>       struct ipr_hrr_queue *hrrq;
>
>       ENTER;
>       for_each_hrrq(hrrq, ioa_cfg) {
>               spin_lock(&hrrq->_lock);
> -             list_for_each_entry_safe(ipr_cmd,
> -                                     temp, &hrrq->hrrq_pending_q, queue) {
> -                     list_move_tail(&ipr_cmd->queue, &hrrq->hrrq_error_q);
> -
> -                     ipr_cmd->s.ioasa.hdr.ioasc =
> -                             cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
> -                     ipr_cmd->s.ioasa.hdr.ilid =
> -                             cpu_to_be32(IPR_DRIVER_ILID);
> -
> -                     if (ipr_cmd->scsi_cmd)
> -                             ipr_cmd->fast_done = ipr_scsi_eh_done;
> -                     else if (ipr_cmd->qc)
> -                             ipr_cmd->fast_done = ipr_sata_eh_done;
> +             for_each_active_cmd(ipr_cmd, hrrq) {
> +                     if (ipr_cmd == ioa_cfg->reset_cmd)
> +                             continue;
>
> -                     del_timer(&ipr_cmd->timer);
> +                     if (!ipr_cmnd_complete(ipr_cmd)) {
> +                             list_add_tail(&ipr_cmd->queue, 
> &hrrq->hrrq_error_q);
> +                             ipr_cmd->s.ioasa.hdr.ioasc =
> +                                     cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
> +                             ipr_cmd->s.ioasa.hdr.ilid =
> +                                     cpu_to_be32(IPR_DRIVER_ILID);
> +
> +                             if (ipr_cmd->scsi_cmd)
> +                                     ipr_cmd->fast_done = ipr_scsi_eh_done;
> +                             else if (ipr_cmd->qc)
> +                                     ipr_cmd->fast_done = ipr_sata_eh_done;
> +
> +                             del_timer(&ipr_cmd->timer);
> +                     }
>               }
>               spin_unlock(&hrrq->_lock);
>       }
> @@ -1010,8 +1012,6 @@ static void ipr_do_req(struct ipr_cmnd *
>                      void (*done) (struct ipr_cmnd *),
>                      void (*timeout_func) (struct ipr_cmnd *), u32 timeout)
>  {
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
> -
>       ipr_cmd->done = done;
>
>       ipr_cmd->timer.data = (unsigned long) ipr_cmd;
> @@ -1145,7 +1145,6 @@ static void ipr_send_hcam(struct ipr_ioa
>
>       if (ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
>               ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
> -             list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
>               list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q);
>
>               ipr_cmd->u.hostrcb = hostrcb;
> @@ -1534,7 +1533,7 @@ static void ipr_process_ccn(struct ipr_c
>       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
>
>       list_del_init(&hostrcb->queue);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>
>       if (ioasc) {
>               if (ioasc != IPR_IOASC_IOA_WAS_RESET &&
> @@ -2654,7 +2653,7 @@ static void ipr_process_error(struct ipr
>               fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc);
>
>       list_del_init(&hostrcb->queue);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>
>       if (!ioasc) {
>               ipr_handle_log_data(ioa_cfg, hostrcb);
> @@ -5075,7 +5074,7 @@ static int ipr_wait_for_ops(struct ipr_i
>
>               for_each_hrrq(hrrq, ioa_cfg) {
>                       spin_lock_irqsave(hrrq->lock, flags);
> -                     list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, 
> queue) {
> +                     for_each_active_cmd(ipr_cmd, hrrq) {
>                               if (match(ipr_cmd, device)) {
>                                       ipr_cmd->eh_comp = &comp;
>                                       wait++;
> @@ -5092,7 +5091,7 @@ static int ipr_wait_for_ops(struct ipr_i
>
>                               for_each_hrrq(hrrq, ioa_cfg) {
>                                       spin_lock_irqsave(hrrq->lock, flags);
> -                                     list_for_each_entry(ipr_cmd, 
> &hrrq->hrrq_pending_q, queue) {
> +                                     for_each_active_cmd(ipr_cmd, hrrq) {
>                                               if (match(ipr_cmd, device)) {
>                                                       ipr_cmd->eh_comp = NULL;
>                                                       wait++;
> @@ -5193,7 +5192,7 @@ static int ipr_device_reset(struct ipr_i
>
>       ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
>       ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       if (ipr_is_gata(res) && res->sata_port && ioasc != 
> IPR_IOASC_IOA_WAS_RESET) {
>               if (ipr_cmd->ioa_cfg->sis64)
>                       memcpy(&res->sata_port->ioasa, 
> &ipr_cmd->s.ioasa64.u.gata,
> @@ -5294,7 +5293,7 @@ static int __ipr_eh_dev_reset(struct scs
>
>       for_each_hrrq(hrrq, ioa_cfg) {
>               spin_lock(&hrrq->_lock);
> -             list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
> +             for_each_active_cmd(ipr_cmd, hrrq) {
>                       if (ipr_cmd->ioarcb.res_handle == res->res_handle) {
>                               if (ipr_cmd->scsi_cmd)
>                                       ipr_cmd->done = ipr_scsi_eh_done;
> @@ -5362,7 +5361,7 @@ static void ipr_bus_reset_done(struct ip
>       else
>               ipr_cmd->sibling->done(ipr_cmd->sibling);
>
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       LEAVE;
>  }
>
> @@ -5451,7 +5450,7 @@ static int ipr_cancel_op(struct scsi_cmn
>
>       for_each_hrrq(hrrq, ioa_cfg) {
>               spin_lock(&hrrq->_lock);
> -             list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
> +             for_each_active_cmd(ipr_cmd, hrrq) {
>                       if (ipr_cmd->scsi_cmd == scsi_cmd) {
>                               ipr_cmd->done = ipr_scsi_eh_done;
>                               op_found = 1;
> @@ -5485,7 +5484,7 @@ static int ipr_cancel_op(struct scsi_cmn
>               ipr_trace;
>       }
>
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       if (!ipr_is_naca_model(res))
>               res->needs_sync_complete = 1;
>
> @@ -5634,7 +5633,6 @@ static irqreturn_t ipr_handle_other_inte
>                               /* clear stage change */
>                               writel(IPR_PCII_IPL_STAGE_CHANGE, 
> ioa_cfg->regs.clr_interrupt_reg);
>                               int_reg = 
> readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
> -                             list_del(&ioa_cfg->reset_cmd->queue);
>                               del_timer(&ioa_cfg->reset_cmd->timer);
>                               ipr_reset_ioa_job(ioa_cfg->reset_cmd);
>                               return IRQ_HANDLED;
> @@ -5649,7 +5647,6 @@ static irqreturn_t ipr_handle_other_inte
>               writel(IPR_PCII_IOA_TRANS_TO_OPER, 
> ioa_cfg->regs.set_interrupt_mask_reg);
>               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
>
> -             list_del(&ioa_cfg->reset_cmd->queue);
>               del_timer(&ioa_cfg->reset_cmd->timer);
>               ipr_reset_ioa_job(ioa_cfg->reset_cmd);
>       } else if ((int_reg & IPR_PCII_HRRQ_UPDATED) == int_reg) {
> @@ -5731,9 +5728,11 @@ static int ipr_process_hrrq(struct ipr_h
>               ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
>               ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
>
> -             ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
> -
> -             list_move_tail(&ipr_cmd->queue, doneq);
> +             if (!ipr_cmnd_complete(ipr_cmd)) {
> +                     ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
> +                     list_add_tail(&ipr_cmd->queue, doneq);
> +                     num_hrrq++;
> +             }
>
>               if (hrr_queue->hrrq_curr < hrr_queue->hrrq_end) {
>                       hrr_queue->hrrq_curr++;
> @@ -5741,7 +5740,7 @@ static int ipr_process_hrrq(struct ipr_h
>                       hrr_queue->hrrq_curr = hrr_queue->hrrq_start;
>                       hrr_queue->toggle_bit ^= 1u;
>               }
> -             num_hrrq++;
> +
>               if (budget > 0 && num_hrrq >= budget)
>                       break;
>       }
> @@ -6039,7 +6038,7 @@ static void ipr_erp_done(struct ipr_cmnd
>               res->in_erp = 0;
>       }
>       scsi_dma_unmap(ipr_cmd->scsi_cmd);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       scsi_cmd->scsi_done(scsi_cmd);
>  }
>
> @@ -6056,6 +6055,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(
>       struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
>       dma_addr_t dma_addr = ipr_cmd->dma_addr;
>
> +     ipr_cmnd_clear_complete(ipr_cmd);
>       memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
>       ioarcb->data_transfer_length = 0;
>       ioarcb->read_data_transfer_length = 0;
> @@ -6430,7 +6430,7 @@ static void ipr_erp_start(struct ipr_ioa
>       }
>
>       scsi_dma_unmap(ipr_cmd->scsi_cmd);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       scsi_cmd->scsi_done(scsi_cmd);
>  }
>
> @@ -6455,9 +6455,8 @@ static void ipr_scsi_done(struct ipr_cmn
>
>       if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
>               scsi_dma_unmap(scsi_cmd);
> -
>               spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags);
> -             list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +             ipr_free_cmd(ipr_cmd);
>               scsi_cmd->scsi_done(scsi_cmd);
>               spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags);
>       } else {
> @@ -6514,32 +6513,9 @@ static int ipr_queuecommand(struct Scsi_
>
>       hrrq = &ioa_cfg->hrrq[hrrq_id];
>
> -     spin_lock_irqsave(hrrq->lock, hrrq_flags);
> -     /*
> -      * We are currently blocking all devices due to a host reset
> -      * We have told the host to stop giving us new requests, but
> -      * ERP ops don't count. FIXME
> -      */
> -     if (unlikely(!hrrq->allow_cmds && !hrrq->ioa_is_dead && 
> !hrrq->removing_ioa)) {
> -             spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
> -             return SCSI_MLQUEUE_HOST_BUSY;
> -     }
> -
> -     /*
> -      * FIXME - Create scsi_set_host_offline interface
> -      *  and the ioa_is_dead check can be removed
> -      */
> -     if (unlikely(hrrq->ioa_is_dead || hrrq->removing_ioa || !res)) {
> -             spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
> -             goto err_nodev;
> -     }
> -
>       ipr_cmd = __ipr_get_free_ipr_cmnd(hrrq);
> -     if (ipr_cmd == NULL) {
> -             spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
> +     if (ipr_cmd == NULL)
>               return SCSI_MLQUEUE_HOST_BUSY;
> -     }
> -     spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
>
>       ipr_init_ipr_cmnd(ipr_cmd, ipr_scsi_done);
>       ioarcb = &ipr_cmd->ioarcb;
> @@ -6585,16 +6561,16 @@ static int ipr_queuecommand(struct Scsi_
>               rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
>
>       spin_lock_irqsave(hrrq->lock, hrrq_flags);
> -     if (unlikely(rc || (!hrrq->allow_cmds && !hrrq->ioa_is_dead))) {
> -             list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
> +     if (unlikely(rc || (!hrrq->allow_cmds && !hrrq->ioa_is_dead && 
> !hrrq->removing_ioa))) {
> +             ipr_free_cmd(ipr_cmd);
>               spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
>               if (!rc)
>                       scsi_dma_unmap(scsi_cmd);
>               return SCSI_MLQUEUE_HOST_BUSY;
>       }
>
> -     if (unlikely(hrrq->ioa_is_dead)) {
> -             list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
> +     if (unlikely(hrrq->ioa_is_dead || hrrq->removing_ioa)) {
> +             ipr_free_cmd(ipr_cmd);
>               spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
>               scsi_dma_unmap(scsi_cmd);
>               goto err_nodev;
> @@ -6605,7 +6581,6 @@ static int ipr_queuecommand(struct Scsi_
>               ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_SYNC_COMPLETE;
>               res->needs_sync_complete = 0;
>       }
> -     list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_pending_q);
>       ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_GET_RES_PHYS_LOC(res));
>       ipr_send_command(ipr_cmd);
>       spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
> @@ -6721,7 +6696,7 @@ static void ipr_ata_post_internal(struct
>
>       for_each_hrrq(hrrq, ioa_cfg) {
>               spin_lock(&hrrq->_lock);
> -             list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
> +             for_each_active_cmd(ipr_cmd, hrrq) {
>                       if (ipr_cmd->qc == qc)
>                               found++;
>               }
> @@ -6794,7 +6769,7 @@ static void ipr_sata_done(struct ipr_cmn
>               qc->err_mask |= __ac_err_mask(sata_port->ioasa.status);
>       else
>               qc->err_mask |= ac_err_mask(sata_port->ioasa.status);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       spin_unlock_irqrestore(ipr_cmd->hrrq->lock, flags);
>       ata_qc_complete(qc);
>  }
> @@ -6960,7 +6935,7 @@ static unsigned int ipr_qc_issue(struct
>       spin_lock(&ipr_cmd->hrrq->_lock);
>       if (unlikely(!ipr_cmd->hrrq->allow_cmds ||
>                       ipr_cmd->hrrq->ioa_is_dead)) {
> -             list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +             ipr_free_cmd(ipr_cmd);
>               spin_unlock(&ipr_cmd->hrrq->_lock);
>               return AC_ERR_SYSTEM;
>       }
> @@ -6977,7 +6952,6 @@ static unsigned int ipr_qc_issue(struct
>       memset(regs, 0, sizeof(*regs));
>       ioarcb->add_cmd_parms_len = cpu_to_be16(sizeof(*regs));
>
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
>       ipr_cmd->qc = qc;
>       ipr_cmd->done = ipr_sata_done;
>       ipr_cmd->ioarcb.res_handle = res->res_handle;
> @@ -7157,7 +7131,7 @@ static int ipr_ioa_bringdown_done(struct
>       ipr_send_back_failed_ops(ioa_cfg);
>       spin_lock_irq(ioa_cfg->host->host_lock);
>
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       wake_up_all(&ioa_cfg->reset_wait_q);
>       LEAVE;
>
> @@ -7216,7 +7190,7 @@ static int ipr_ioa_reset_done(struct ipr
>       dev_info(&ioa_cfg->pdev->dev, "IOA initialized.\n");
>
>       ioa_cfg->reset_retries = 0;
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       wake_up_all(&ioa_cfg->reset_wait_q);
>
>       spin_unlock_irq(ioa_cfg->host->host_lock);
> @@ -7558,7 +7532,7 @@ static int ipr_reset_cmd_failed(struct i
>               ipr_cmd->ioarcb.cmd_pkt.cdb[0], ioasc);
>
>       ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>       return IPR_RC_JOB_RETURN;
>  }
>
> @@ -8065,8 +8039,7 @@ static int ipr_ioafp_page0_inquiry(struc
>               if (!ipr_testmode) {
>                       ioa_cfg->reset_retries += IPR_NUM_RESET_RELOAD_RETRIES;
>                       ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
> -                     list_add_tail(&ipr_cmd->queue,
> -                                     &ioa_cfg->hrrq->hrrq_free_q);
> +                     ipr_free_cmd(ipr_cmd);
>                       return IPR_RC_JOB_RETURN;
>               }
>       }
> @@ -8208,8 +8181,8 @@ static void ipr_reset_timer_done(struct
>       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
>
>       if (ioa_cfg->reset_cmd == ipr_cmd) {
> -             list_del(&ipr_cmd->queue);
> -             ipr_cmd->done(ipr_cmd);
> +             if (!ipr_cmnd_complete(ipr_cmd))
> +                     ipr_cmd->done(ipr_cmd);
>       }
>
>       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
> @@ -8234,7 +8207,6 @@ static void ipr_reset_start_timer(struct
>  {
>
>       ENTER;
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
>       ipr_cmd->done = ipr_reset_ioa_job;
>
>       ipr_cmd->timer.data = (unsigned long) ipr_cmd;
> @@ -8329,8 +8301,6 @@ static int ipr_reset_next_stage(struct i
>       ipr_cmd->done = ipr_reset_ioa_job;
>       add_timer(&ipr_cmd->timer);
>
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
> -
>       return IPR_RC_JOB_RETURN;
>  }
>
> @@ -8400,7 +8370,6 @@ static int ipr_reset_enable_ioa(struct i
>       ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
>       ipr_cmd->done = ipr_reset_ioa_job;
>       add_timer(&ipr_cmd->timer);
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
>
>       LEAVE;
>       return IPR_RC_JOB_RETURN;
> @@ -8931,10 +8900,10 @@ static int ipr_reset_cancel_hcam_done(st
>
>       for_each_hrrq(hrrq, ioa_cfg) {
>               spin_lock(&hrrq->_lock);
> -             list_for_each_entry(loop_cmd, &hrrq->hrrq_pending_q, queue) {
> +             for_each_active_cmd(loop_cmd, hrrq) {
>                       count++;
>                       ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
> -                     list_add_tail(&ipr_cmd->queue, 
> &ipr_cmd->hrrq->hrrq_free_q);
> +                     ipr_free_cmd(ipr_cmd);
>                       rc = IPR_RC_JOB_RETURN;
>                       break;
>               }
> @@ -8970,7 +8939,7 @@ static int ipr_reset_cancel_hcam(struct
>
>       if (!hrrq->ioa_is_dead) {
>               if (!list_empty(&ioa_cfg->hostrcb_pending_q)) {
> -                     list_for_each_entry(hcam_cmd, &hrrq->hrrq_pending_q, 
> queue) {
> +                     for_each_active_cmd(hcam_cmd, hrrq) {
>                               if (hcam_cmd->ioarcb.cmd_pkt.cdb[0] != 
> IPR_HOST_CONTROLLED_ASYNC)
>                                       continue;
>
> @@ -9137,8 +9106,7 @@ static void ipr_reset_ioa_job(struct ipr
>                        * We are doing nested adapter resets and this is
>                        * not the current reset job.
>                        */
> -                     list_add_tail(&ipr_cmd->queue,
> -                                     &ipr_cmd->hrrq->hrrq_free_q);
> +                     ipr_free_cmd(ipr_cmd);
>                       return;
>               }
>
> @@ -9275,7 +9243,6 @@ static int ipr_reset_freeze(struct ipr_c
>               spin_unlock(&ioa_cfg->hrrq[i]._lock);
>       }
>       wmb();
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
>       ipr_cmd->done = ipr_reset_ioa_job;
>       return IPR_RC_JOB_RETURN;
>  }
> @@ -9456,6 +9423,9 @@ static void ipr_free_cmd_blks(struct ipr
>               }
>       }
>
> +     for (i = 0; i < ioa_cfg->hrrq_num; i++)
> +             kfree(ioa_cfg->hrrq[i].active_map);
> +
>       if (ioa_cfg->ipr_cmd_pool)
>               dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
>
> @@ -9613,6 +9583,8 @@ static int ipr_alloc_cmd_blks(struct ipr
>                       ioa_cfg->hrrq[i].max_cmd_id = (entries_each_hrrq - 1);
>               }
>               ioa_cfg->hrrq[i].size = entries_each_hrrq;
> +             ioa_cfg->hrrq[i].active_map = 
> kcalloc(BITS_TO_LONGS(entries_each_hrrq),
> +                                                   sizeof(unsigned long), 
> GFP_KERNEL);
>       }
>
>       BUG_ON(ioa_cfg->hrrq_num == 0);
> @@ -9664,7 +9636,6 @@ static int ipr_alloc_cmd_blks(struct ipr
>
>               ipr_cmd->ioarcb.cmd_pkt.hrrq_id = hrrq_id;
>               ipr_cmd->hrrq = &ioa_cfg->hrrq[hrrq_id];
> -             list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
>               if (i >= ioa_cfg->hrrq[hrrq_id].max_cmd_id)
>                       hrrq_id++;
>       }
> @@ -9911,8 +9882,6 @@ static void ipr_init_ioa_cfg(struct ipr_
>       pci_set_drvdata(pdev, ioa_cfg);
>
>       for (i = 0; i < ARRAY_SIZE(ioa_cfg->hrrq); i++) {
> -             INIT_LIST_HEAD(&ioa_cfg->hrrq[i].hrrq_free_q);
> -             INIT_LIST_HEAD(&ioa_cfg->hrrq[i].hrrq_pending_q);
>               INIT_LIST_HEAD(&ioa_cfg->hrrq[i].hrrq_error_q);
>               spin_lock_init(&ioa_cfg->hrrq[i]._lock);
>               if (i == 0)
> @@ -10820,9 +10789,10 @@ static struct pci_driver ipr_driver = {
>   **/
>  static void ipr_halt_done(struct ipr_cmnd *ipr_cmd)
>  {
> -     list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
> +     ipr_free_cmd(ipr_cmd);
>  }
>
> +
>  /**
>   * ipr_halt - Issue shutdown prepare to all adapters
>   *
> _
>
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Iprdd-devel mailing list
> Iprdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/iprdd-devel
>

-- 
Gabriel Krisman Bertazi


------------------------------------------------------------------------------
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to