All of lore.kernel.org
 help / color / mirror / Atom feed
From: <Don.Brace@microchip.com>
To: <mwilck@suse.com>, <Kevin.Barnett@microchip.com>,
	<Scott.Teel@microchip.com>, <Justin.Lindley@microchip.com>,
	<Scott.Benesh@microchip.com>, <Gerry.Morong@microchip.com>,
	<Mahesh.Rajashekhara@microchip.com>, <hch@infradead.org>,
	<jejb@linux.vnet.ibm.com>, <joseph.szczypek@hpe.com>,
	<POSWALD@suse.com>
Cc: <linux-scsi@vger.kernel.org>
Subject: RE: [PATCH V3 14/25] smartpqi: fix driver synchronization issues
Date: Fri, 15 Jan 2021 21:13:22 +0000	[thread overview]
Message-ID: <SN6PR11MB28487F1C94939FC4B096E0CFE1A70@SN6PR11MB2848.namprd11.prod.outlook.com> (raw)
In-Reply-To: <76f8c5cbdd1722eecdda017c46c0d617f5086e1d.camel@suse.com>

-----Original Message-----
From: Martin Wilck [mailto:mwilck@suse.com] 
Subject: Re: [PATCH V3 14/25] smartpqi: fix driver synchronization issues

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

On Thu, 2020-12-10 at 14:35 -0600, Don Brace wrote:
> From: Kevin Barnett <kevin.barnett@microchip.com>
>
> * synchronize: LUN resets, shutdowns, suspend, hibernate,
>   OFA, and controller offline events.
> * prevent I/O during the the above conditions.

This description is too terse for a complex patch like this.

Could you please explain how this synchronization is supposed to work
on the different layers, and for the different code paths for different
types of IO events that are apparently not all handled equally wrt
blocking, and how the different flags and mutexes are supposed to
interact? I'd also appreciate some explanation what sort of "driver
synchronization issues" you have seen, and how exactly this patch is
supposed to fix them.

Please forgive me if I ask dumb questions or make dumb comments below,
I don't get the full picture of what you're trying to achieve.

The patch does not only address synchronization issues; it also changes
various other things that (given the size of the patch) should better
be handled elsewhere. I believe this patch could easily be split into
4 or more separate independent patches, which would ease review
considerably. I've added remarks below where I thought one or more
hunks could be separated out.

Thanks,
Martin

Don: I refactored this patch into 10 patches:
+ smartpqi-remove-timeouts-from-internal-cmds
+ smartpqi-add-support-for-wwid
+ smartpqi-update-event-handler
+ smartpqi-update-soft-reset
+ smartpqi-update-device-resets
+ smartpqi-update-suspend-and-resume
+ smartpqi-update-raid-bypass-handling
+ smartpqi-update-ofa-management
+ smartpqi-update-device-scan-operations
+ smartpqi-fix-driver-synchronization-issues

I will post them after some internal review in V4. I may make some changes to the patch titles...
I'll answer more questions that you have asked in another e-mail.


> @@ -245,14 +246,66 @@ static inline void pqi_save_ctrl_mode(struct
> pqi_ctrl_info *ctrl_info,
>         sis_write_driver_scratch(ctrl_info, mode);
>  }
>
> +static inline void pqi_ctrl_block_scan(struct pqi_ctrl_info
> *ctrl_info)
> +{
> +       ctrl_info->scan_blocked = true;
> +       mutex_lock(&ctrl_info->scan_mutex);
> +}

What do you need scan_blocked for? Can't you simply use
mutex_is_locked(&ctrl_info->scan_mutex)?
OTOH, using a mutex for this kind of condition feels dangerous
to me, see remark about ota_mutex() below.
Have you considered using a completion for this?

> +
> +static inline void pqi_ctrl_unblock_scan(struct pqi_ctrl_info
> *ctrl_info)
> +{
> +       ctrl_info->scan_blocked = false;
> +       mutex_unlock(&ctrl_info->scan_mutex);
> +}
> +
> +static inline bool pqi_ctrl_scan_blocked(struct pqi_ctrl_info
> *ctrl_info)
> +{
> +       return ctrl_info->scan_blocked;
> +}
> +
>  static inline void pqi_ctrl_block_device_reset(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       ctrl_info->block_device_reset = true;
> +       mutex_lock(&ctrl_info->lun_reset_mutex);
> +}
> +
> +static inline void pqi_ctrl_unblock_device_reset(struct
> pqi_ctrl_info *ctrl_info)
> +{
> +       mutex_unlock(&ctrl_info->lun_reset_mutex);
> +}
> +
> +static inline void pqi_scsi_block_requests(struct pqi_ctrl_info
> *ctrl_info)
> +{
> +       struct Scsi_Host *shost;
> +       unsigned int num_loops;
> +       int msecs_sleep;
> +
> +       shost = ctrl_info->scsi_host;
> +
> +       scsi_block_requests(shost);
> +
> +       num_loops = 0;
> +       msecs_sleep = 20;
> +       while (scsi_host_busy(shost)) {
> +               num_loops++;
> +               if (num_loops == 10)
> +                       msecs_sleep = 500;
> +               msleep(msecs_sleep);
> +       }
> +}

Waiting for !scsi_host_busy() here looks like a layering violation to
me. Can't you use wait_event{_timeout}() here and wait for the sum of
of device->scsi_cmds_outstanding over to become zero (waking up the
queue in pqi_prep_for_scsi_done())? You could use the
total_scmnds_outstanding count that you introduce in patch 15/25.

Also, how does this interact/interfere with scsi EH?

> +
> +static inline void pqi_scsi_unblock_requests(struct pqi_ctrl_info
> *ctrl_info)
> +{
> +       scsi_unblock_requests(ctrl_info->scsi_host);
> +}
> +
> +static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info)
> +{
> +       atomic_inc(&ctrl_info->num_busy_threads);
>  }
>
> -static inline bool pqi_device_reset_blocked(struct pqi_ctrl_info
> *ctrl_info)
> +static inline void pqi_ctrl_unbusy(struct pqi_ctrl_info *ctrl_info)
>  {
> -       return ctrl_info->block_device_reset;
> +       atomic_dec(&ctrl_info->num_busy_threads);
>  }
>
>  static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info)
> @@ -263,44 +316,23 @@ static inline bool pqi_ctrl_blocked(struct
> pqi_ctrl_info *ctrl_info)
>  static inline void pqi_ctrl_block_requests(struct pqi_ctrl_info
> *ctrl_info)
>  {
>         ctrl_info->block_requests = true;
> -       scsi_block_requests(ctrl_info->scsi_host);
>  }
>
>  static inline void pqi_ctrl_unblock_requests(struct pqi_ctrl_info
> *ctrl_info)
>  {
>         ctrl_info->block_requests = false;
>         wake_up_all(&ctrl_info->block_requests_wait);
> -       pqi_retry_raid_bypass_requests(ctrl_info);
> -       scsi_unblock_requests(ctrl_info->scsi_host);
>  }
>
> -static unsigned long pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info
> *ctrl_info,
> -       unsigned long timeout_msecs)
> +static void pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       unsigned long remaining_msecs;
> -
>         if (!pqi_ctrl_blocked(ctrl_info))
> -               return timeout_msecs;
> +               return;
>
>         atomic_inc(&ctrl_info->num_blocked_threads);
> -
> -       if (timeout_msecs == NO_TIMEOUT) {
> -               wait_event(ctrl_info->block_requests_wait,
> -                       !pqi_ctrl_blocked(ctrl_info));
> -               remaining_msecs = timeout_msecs;
> -       } else {
> -               unsigned long remaining_jiffies;
> -
> -               remaining_jiffies =
> -                       wait_event_timeout(ctrl_info-
> > block_requests_wait,
> -                               !pqi_ctrl_blocked(ctrl_info),
> -                               msecs_to_jiffies(timeout_msecs));
> -               remaining_msecs =
> jiffies_to_msecs(remaining_jiffies);
> -       }
> -
> +       wait_event(ctrl_info->block_requests_wait,
> +               !pqi_ctrl_blocked(ctrl_info));
>         atomic_dec(&ctrl_info->num_blocked_threads);
> -
> -       return remaining_msecs;
>  }
>
>  static inline void pqi_ctrl_wait_until_quiesced(struct pqi_ctrl_info
> *ctrl_info)
> @@ -315,34 +347,25 @@ static inline bool pqi_device_offline(struct
> pqi_scsi_dev *device)
>         return device->device_offline;
>  }
>
> -static inline void pqi_device_reset_start(struct pqi_scsi_dev
> *device)
> -{
> -       device->in_reset = true;
> -}
> -
> -static inline void pqi_device_reset_done(struct pqi_scsi_dev
> *device)
> -{
> -       device->in_reset = false;
> -}
> -
> -static inline bool pqi_device_in_reset(struct pqi_scsi_dev *device)
> +static inline void pqi_ctrl_ofa_start(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       return device->in_reset;
> +       mutex_lock(&ctrl_info->ofa_mutex);
>  }
>
> -static inline void pqi_ctrl_ofa_start(struct pqi_ctrl_info
> *ctrl_info)
> +static inline void pqi_ctrl_ofa_done(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       ctrl_info->in_ofa = true;
> +       mutex_unlock(&ctrl_info->ofa_mutex);
>  }

pqi_ctrl_ofa_done() is called in several places. For me, it's non-
obvious whether ofa_mutex is guaranteed to be locked when this happens.
It would be an error to call mutex_unlock() if that's not the case.
Also, is it always guaranteed that "The context (task) that acquired
the lock also releases it"
(https://www.kernel.org/doc/html/latest/locking/locktypes.html)?
If feel that's rather not the case, as pqi_ctrl_ofa_start() is run from
a work queue, whereas pqi_ctrl_ofa_done() is not, afaics.

Have you considered using a completion?
Or can you add some explanatory comments?

> -static inline void pqi_ctrl_ofa_done(struct pqi_ctrl_info
> *ctrl_info)
> +static inline void pqi_wait_until_ofa_finished(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       ctrl_info->in_ofa = false;
> +       mutex_lock(&ctrl_info->ofa_mutex);
> +       mutex_unlock(&ctrl_info->ofa_mutex);
>  }
>
> -static inline bool pqi_ctrl_in_ofa(struct pqi_ctrl_info *ctrl_info)
> +static inline bool pqi_ofa_in_progress(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       return ctrl_info->in_ofa;
> +       return mutex_is_locked(&ctrl_info->ofa_mutex);
>  }
>
>  static inline void pqi_device_remove_start(struct pqi_scsi_dev
> *device)
> @@ -355,14 +378,20 @@ static inline bool pqi_device_in_remove(struct
> pqi_scsi_dev *device)
>         return device->in_remove;
>  }
>
> -static inline void pqi_ctrl_shutdown_start(struct pqi_ctrl_info
> *ctrl_info)
> +static inline int pqi_event_type_to_event_index(unsigned int
> event_type)
>  {
> -       ctrl_info->in_shutdown = true;
> +       int index;
> +
> +       for (index = 0; index <
> ARRAY_SIZE(pqi_supported_event_types); index++)
> +               if (event_type == pqi_supported_event_types[index])
> +                       return index;
> +
> +       return -1;
>  }
>
> -static inline bool pqi_ctrl_in_shutdown(struct pqi_ctrl_info
> *ctrl_info)
> +static inline bool pqi_is_supported_event(unsigned int event_type)
>  {
> -       return ctrl_info->in_shutdown;
> +       return pqi_event_type_to_event_index(event_type) != -1;
>  }
>
>  static inline void pqi_schedule_rescan_worker_with_delay(struct
> pqi_ctrl_info *ctrl_info,
> @@ -370,8 +399,6 @@ static inline void
> pqi_schedule_rescan_worker_with_delay(struct pqi_ctrl_info *c
>  {
>         if (pqi_ctrl_offline(ctrl_info))
>                 return;
> -       if (pqi_ctrl_in_ofa(ctrl_info))
> -               return;
>
>         schedule_delayed_work(&ctrl_info->rescan_work, delay);
>  }
> @@ -408,22 +435,15 @@ static inline u32
> pqi_read_heartbeat_counter(struct pqi_ctrl_info *ctrl_info)
>
>  static inline u8 pqi_read_soft_reset_status(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       if (!ctrl_info->soft_reset_status)
> -               return 0;
> -
>         return readb(ctrl_info->soft_reset_status);
>  }

The new treatment of soft_reset_status is unrelated to the
synchronization issues mentioned in the patch description.

>
> -static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info
> *ctrl_info,
> -       u8 clear)
> +static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info
> *ctrl_info)
>  {
>         u8 status;
>
> -       if (!ctrl_info->soft_reset_status)
> -               return;
> -
>         status = pqi_read_soft_reset_status(ctrl_info);
> -       status &= ~clear;
> +       status &= ~PQI_SOFT_RESET_ABORT;
>         writeb(status, ctrl_info->soft_reset_status);
>  }
>
> @@ -512,6 +532,7 @@ static int pqi_build_raid_path_request(struct
> pqi_ctrl_info *ctrl_info,
>                 put_unaligned_be32(cdb_length, &cdb[6]);
>                 break;
>         case SA_FLUSH_CACHE:
> +               request->header.driver_flags =
> PQI_DRIVER_NONBLOCKABLE_REQUEST;
>                 request->data_direction = SOP_WRITE_FLAG;
>                 cdb[0] = BMIC_WRITE;
>                 cdb[6] = BMIC_FLUSH_CACHE;
> @@ -606,7 +627,7 @@ static void pqi_free_io_request(struct
> pqi_io_request *io_request)
>
>  static int pqi_send_scsi_raid_request(struct pqi_ctrl_info
> *ctrl_info, u8 cmd,
>         u8 *scsi3addr, void *buffer, size_t buffer_length, u16
> vpd_page,
> -       struct pqi_raid_error_info *error_info, unsigned long
> timeout_msecs)
> +       struct pqi_raid_error_info *error_info)
>  {
>         int rc;
>         struct pqi_raid_path_request request;
> @@ -618,7 +639,7 @@ static int pqi_send_scsi_raid_request(struct
> pqi_ctrl_info *ctrl_info, u8 cmd,
>                 return rc;
>
>         rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header, 0,
> -               error_info, timeout_msecs);
> +               error_info);
>
>         pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1,
> dir);
>
> @@ -631,7 +652,7 @@ static inline int
> pqi_send_ctrl_raid_request(struct pqi_ctrl_info *ctrl_info,
>         u8 cmd, void *buffer, size_t buffer_length)
>  {
>         return pqi_send_scsi_raid_request(ctrl_info, cmd,
> RAID_CTLR_LUNID,
> -               buffer, buffer_length, 0, NULL, NO_TIMEOUT);
> +               buffer, buffer_length, 0, NULL);
>  }
>
>  static inline int pqi_send_ctrl_raid_with_error(struct pqi_ctrl_info
> *ctrl_info,
> @@ -639,7 +660,7 @@ static inline int
> pqi_send_ctrl_raid_with_error(struct pqi_ctrl_info *ctrl_info,
>         struct pqi_raid_error_info *error_info)
>  {
>         return pqi_send_scsi_raid_request(ctrl_info, cmd,
> RAID_CTLR_LUNID,
> -               buffer, buffer_length, 0, error_info, NO_TIMEOUT);
> +               buffer, buffer_length, 0, error_info);
>  }
>
>  static inline int pqi_identify_controller(struct pqi_ctrl_info
> *ctrl_info,
> @@ -661,7 +682,7 @@ static inline int pqi_scsi_inquiry(struct
> pqi_ctrl_info *ctrl_info,
>         u8 *scsi3addr, u16 vpd_page, void *buffer, size_t
> buffer_length)
>  {
>         return pqi_send_scsi_raid_request(ctrl_info, INQUIRY,
> scsi3addr,
> -               buffer, buffer_length, vpd_page, NULL, NO_TIMEOUT);
> +               buffer, buffer_length, vpd_page, NULL);
>  }
>
>  static int pqi_identify_physical_device(struct pqi_ctrl_info
> *ctrl_info,
> @@ -683,8 +704,7 @@ static int pqi_identify_physical_device(struct
> pqi_ctrl_info *ctrl_info,
>         request.cdb[2] = (u8)bmic_device_index;
>         request.cdb[9] = (u8)(bmic_device_index >> 8);
>
> -       rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header,
> -               0, NULL, NO_TIMEOUT);
> +       rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header, 0, NULL);
>
>         pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1,
> dir);
>
> @@ -741,7 +761,7 @@ static int
> pqi_get_advanced_raid_bypass_config(struct pqi_ctrl_info *ctrl_info)
>         request.cdb[2] = BMIC_SENSE_FEATURE_IO_PAGE;
>         request.cdb[3] = BMIC_SENSE_FEATURE_IO_PAGE_AIO_SUBPAGE;
>
> -       rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header, 0, NULL, NO_TIMEOUT);
> +       rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header, 0, NULL);
>
>         pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1,
> dir);
>
> @@ -794,13 +814,6 @@ static int pqi_flush_cache(struct pqi_ctrl_info
> *ctrl_info,
>         int rc;
>         struct bmic_flush_cache *flush_cache;
>
> -       /*
> -        * Don't bother trying to flush the cache if the controller
> is
> -        * locked up.
> -        */
> -       if (pqi_ctrl_offline(ctrl_info))
> -               return -ENXIO;
> -
>         flush_cache = kzalloc(sizeof(*flush_cache), GFP_KERNEL);
>         if (!flush_cache)
>                 return -ENOMEM;
> @@ -979,9 +992,6 @@ static void pqi_update_time_worker(struct
> work_struct *work)
>         ctrl_info = container_of(to_delayed_work(work), struct
> pqi_ctrl_info,
>                 update_time_work);
>
> -       if (pqi_ctrl_offline(ctrl_info))
> -               return;
> -
>         rc = pqi_write_current_time_to_host_wellness(ctrl_info);
>         if (rc)
>                 dev_warn(&ctrl_info->pci_dev->dev,
> @@ -1271,9 +1281,7 @@ static int pqi_get_raid_map(struct
> pqi_ctrl_info *ctrl_info,
>                 return -ENOMEM;
>
>         rc = pqi_send_scsi_raid_request(ctrl_info, CISS_GET_RAID_MAP,
> -               device->scsi3addr, raid_map, sizeof(*raid_map),
> -               0, NULL, NO_TIMEOUT);
> -
> +               device->scsi3addr, raid_map, sizeof(*raid_map), 0,
> NULL);
>         if (rc)
>                 goto error;
>
> @@ -1288,8 +1296,7 @@ static int pqi_get_raid_map(struct
> pqi_ctrl_info *ctrl_info,
>                         return -ENOMEM;
>
>                 rc = pqi_send_scsi_raid_request(ctrl_info,
> CISS_GET_RAID_MAP,
> -                       device->scsi3addr, raid_map, raid_map_size,
> -                       0, NULL, NO_TIMEOUT);
> +                       device->scsi3addr, raid_map, raid_map_size,
> 0, NULL);
>                 if (rc)
>                         goto error;
>
> @@ -1464,6 +1471,9 @@ static int pqi_get_physical_device_info(struct
> pqi_ctrl_info *ctrl_info,
>                 sizeof(device->phys_connector));
>         device->bay = id_phys->phys_bay_in_box;
>
> +       memcpy(&device->page_83_identifier, &id_phys-
> >page_83_identifier,
> +               sizeof(device->page_83_identifier));
> +
>         return 0;
>  }
>

This hunk belongs to the "unique wwid" part, see above.


> @@ -1970,8 +1980,13 @@ static void pqi_update_device_list(struct
> pqi_ctrl_info *ctrl_info,
>
>         spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
> flags);
>
> -       if (pqi_ctrl_in_ofa(ctrl_info))
> -               pqi_ctrl_ofa_done(ctrl_info);
> +       if (pqi_ofa_in_progress(ctrl_info)) {
> +               list_for_each_entry_safe(device, next, &delete_list,
> delete_list_entry)
> +                       if (pqi_is_device_added(device))
> +                               pqi_device_remove_start(device);
> +               pqi_ctrl_unblock_device_reset(ctrl_info);
> +               pqi_scsi_unblock_requests(ctrl_info);
> +       }

I don't understand the purpose of is code. pqi_device_remove_start()
will be called again a few lines below. Why do it twice? I suppose
it's related to the unblocking, but that deserves an explanation.
Also, why do you unblock requests while OFA is "in progress"?

>
>         /* Remove all devices that have gone away. */
>         list_for_each_entry_safe(device, next, &delete_list,
> delete_list_entry) {
> @@ -1993,19 +2008,14 @@ static void pqi_update_device_list(struct
> pqi_ctrl_info *ctrl_info,

The following hunk is unrelated to synchronization.

>          * Notify the SCSI ML if the queue depth of any existing
> device has
>          * changed.
>          */
> -       list_for_each_entry(device, &ctrl_info->scsi_device_list,
> -               scsi_device_list_entry) {
> -               if (device->sdev) {
> -                       if (device->queue_depth !=
> -                               device->advertised_queue_depth) {
> -                               device->advertised_queue_depth =
> device->queue_depth;
> -                               scsi_change_queue_depth(device->sdev,
> -                                       device-
> >advertised_queue_depth);
> -                       }
> -                       if (device->rescan) {
> -                               scsi_rescan_device(&device->sdev-
> >sdev_gendev);
> -                               device->rescan = false;
> -                       }
> +       list_for_each_entry(device, &ctrl_info->scsi_device_list,
> scsi_device_list_entry) {
> +               if (device->sdev && device->queue_depth != device-
> >advertised_queue_depth) {
> +                       device->advertised_queue_depth = device-
> >queue_depth;
> +                       scsi_change_queue_depth(device->sdev, device-
> >advertised_queue_depth);
> +               }
> +               if (device->rescan) {
> +                       scsi_rescan_device(&device->sdev-
> >sdev_gendev);
> +                       device->rescan = false;
>                 }

You've taken the reference to device->sdev->sdev_gendev out of the if
(device->sdev) clause. Can you be certain that device->sdev is non-
NULL?

>         }
>
> @@ -2073,6 +2083,16 @@ static inline bool pqi_expose_device(struct
> pqi_scsi_dev *device)
>         return !device->is_physical_device ||
> !pqi_skip_device(device->scsi3addr);
>  }
>

The following belongs to the "unique wwid" part.

> +static inline void pqi_set_physical_device_wwid(struct pqi_ctrl_info
> *ctrl_info,
> +       struct pqi_scsi_dev *device, struct
> report_phys_lun_extended_entry *phys_lun_ext_entry)
> +{
> +       if (ctrl_info->unique_wwid_in_report_phys_lun_supported ||
> +               pqi_is_device_with_sas_address(device))
> +               device->wwid = phys_lun_ext_entry->wwid;
> +       else
> +               device->wwid =
> cpu_to_be64(get_unaligned_be64(&device->page_83_identifier));
> +}
> +
>  static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
>  {
>         int i;
> @@ -2238,7 +2258,7 @@ static int pqi_update_scsi_devices(struct
> pqi_ctrl_info *ctrl_info)
>                 pqi_assign_bus_target_lun(device);
>
>                 if (device->is_physical_device) {
> -                       device->wwid = phys_lun_ext_entry->wwid;
> +                       pqi_set_physical_device_wwid(ctrl_info,
> device, phys_lun_ext_entry);
>                         if ((phys_lun_ext_entry->device_flags &
>                                 CISS_REPORT_PHYS_DEV_FLAG_AIO_ENABLED
> ) &&
>                                 phys_lun_ext_entry->aio_handle) {
> @@ -2278,21 +2298,27 @@ static int pqi_update_scsi_devices(struct
> pqi_ctrl_info *ctrl_info)
>
>  static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info)
>  {
> -       int rc = 0;
> +       int rc;
> +       int mutex_acquired;
>
>         if (pqi_ctrl_offline(ctrl_info))
>                 return -ENXIO;
>
> -       if (!mutex_trylock(&ctrl_info->scan_mutex)) {
> +       mutex_acquired = mutex_trylock(&ctrl_info->scan_mutex);
> +
> +       if (!mutex_acquired) {
> +               if (pqi_ctrl_scan_blocked(ctrl_info))
> +                       return -EBUSY;
>                 pqi_schedule_rescan_worker_delayed(ctrl_info);
> -               rc = -EINPROGRESS;
> -       } else {
> -               rc = pqi_update_scsi_devices(ctrl_info);
> -               if (rc)
> -
>                        pqi_schedule_rescan_worker_delayed(ctrl_info);
> -               mutex_unlock(&ctrl_info->scan_mutex);
> +               return -EINPROGRESS;
>         }
>
> +       rc = pqi_update_scsi_devices(ctrl_info);
> +       if (rc && !pqi_ctrl_scan_blocked(ctrl_info))
> +               pqi_schedule_rescan_worker_delayed(ctrl_info);
> +
> +       mutex_unlock(&ctrl_info->scan_mutex);
> +
>         return rc;
>  }
>
> @@ -2301,8 +2327,6 @@ static void pqi_scan_start(struct Scsi_Host
> *shost)
>         struct pqi_ctrl_info *ctrl_info;
>
>         ctrl_info = shost_to_hba(shost);
> -       if (pqi_ctrl_in_ofa(ctrl_info))
> -               return;
>
>         pqi_scan_scsi_devices(ctrl_info);
>  }
> @@ -2319,27 +2343,8 @@ static int pqi_scan_finished(struct Scsi_Host
> *shost,
>         return !mutex_is_locked(&ctrl_info->scan_mutex);
>  }
>
> -static void pqi_wait_until_scan_finished(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       mutex_lock(&ctrl_info->scan_mutex);
> -       mutex_unlock(&ctrl_info->scan_mutex);
> -}
> -
> -static void pqi_wait_until_lun_reset_finished(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       mutex_lock(&ctrl_info->lun_reset_mutex);
> -       mutex_unlock(&ctrl_info->lun_reset_mutex);
> -}
> -
> -static void pqi_wait_until_ofa_finished(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       mutex_lock(&ctrl_info->ofa_mutex);
> -       mutex_unlock(&ctrl_info->ofa_mutex);
> -}

Here, again, I wonder if this mutex_lock()/mutex_unlock() approach is
optimal. Have you considered using completions?

See above for rationale.

> -
> -static inline void pqi_set_encryption_info(
> -       struct pqi_encryption_info *encryption_info, struct raid_map
> *raid_map,
> -       u64 first_block)
> +static inline void pqi_set_encryption_info(struct
> pqi_encryption_info *encryption_info,
> +       struct raid_map *raid_map, u64 first_block)
>  {
>         u32 volume_blk_size;

This whitespace change doesn't belong here.

>
> @@ -3251,8 +3256,8 @@ static void pqi_acknowledge_event(struct
> pqi_ctrl_info *ctrl_info,
>         put_unaligned_le16(sizeof(request) -
> PQI_REQUEST_HEADER_LENGTH,
>                 &request.header.iu_length);
>         request.event_type = event->event_type;
> -       request.event_id = event->event_id;
> -       request.additional_event_id = event->additional_event_id;
> +       put_unaligned_le16(event->event_id, &request.event_id);
> +       put_unaligned_le16(event->additional_event_id,
> &request.additional_event_id);

The different treatment of the event_id fields is unrelated to
synchronization, or am I missing something?

>
>         pqi_send_event_ack(ctrl_info, &request, sizeof(request));
>  }
> @@ -3263,8 +3268,8 @@ static void pqi_acknowledge_event(struct
> pqi_ctrl_info *ctrl_info,
>  static enum pqi_soft_reset_status pqi_poll_for_soft_reset_status(
>         struct pqi_ctrl_info *ctrl_info)
>  {
> -       unsigned long timeout;
>         u8 status;
> +       unsigned long timeout;
>
>         timeout = (PQI_SOFT_RESET_STATUS_TIMEOUT_SECS * PQI_HZ) +
> jiffies;
>
> @@ -3276,120 +3281,169 @@ static enum pqi_soft_reset_status
> pqi_poll_for_soft_reset_status(
>                 if (status & PQI_SOFT_RESET_ABORT)
>                         return RESET_ABORT;
>
> +               if (!sis_is_firmware_running(ctrl_info))
> +                       return RESET_NORESPONSE;
> +
>                 if (time_after(jiffies, timeout)) {
> -                       dev_err(&ctrl_info->pci_dev->dev,
> +                       dev_warn(&ctrl_info->pci_dev->dev,
>                                 "timed out waiting for soft reset
> status\n");
>                         return RESET_TIMEDOUT;
>                 }
>
> -               if (!sis_is_firmware_running(ctrl_info))
> -                       return RESET_NORESPONSE;
> -
>                 ssleep(PQI_SOFT_RESET_STATUS_POLL_INTERVAL_SECS);
>         }
>  }
>
> -static void pqi_process_soft_reset(struct pqi_ctrl_info *ctrl_info,
> -       enum pqi_soft_reset_status reset_status)
> +static void pqi_process_soft_reset(struct pqi_ctrl_info *ctrl_info)
>  {
>         int rc;
> +       unsigned int delay_secs;
> +       enum pqi_soft_reset_status reset_status;
> +
> +       if (ctrl_info->soft_reset_handshake_supported)
> +               reset_status =
> pqi_poll_for_soft_reset_status(ctrl_info);
> +       else
> +               reset_status = RESET_INITIATE_FIRMWARE;
> +
> +       pqi_ofa_free_host_buffer(ctrl_info);
> +
> +       delay_secs = PQI_POST_RESET_DELAY_SECS;
>
>         switch (reset_status) {
> -       case RESET_INITIATE_DRIVER:
>         case RESET_TIMEDOUT:
> +               delay_secs =
> PQI_POST_OFA_RESET_DELAY_UPON_TIMEOUT_SECS;
> +               fallthrough;
> +       case RESET_INITIATE_DRIVER:
>                 dev_info(&ctrl_info->pci_dev->dev,
> -                       "resetting controller %u\n", ctrl_info-
> >ctrl_id);
> +                               "Online Firmware Activation:
> resetting controller\n");
>                 sis_soft_reset(ctrl_info);
>                 fallthrough;
>         case RESET_INITIATE_FIRMWARE:
> -               rc = pqi_ofa_ctrl_restart(ctrl_info);
> -               pqi_ofa_free_host_buffer(ctrl_info);
> +               ctrl_info->pqi_mode_enabled = false;
> +               pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
> +               rc = pqi_ofa_ctrl_restart(ctrl_info, delay_secs);
> +               pqi_ctrl_ofa_done(ctrl_info);
>                 dev_info(&ctrl_info->pci_dev->dev,
> -                       "Online Firmware Activation for controller
> %u: %s\n",
> -                       ctrl_info->ctrl_id, rc == 0 ? "SUCCESS" :
> "FAILED");
> +                               "Online Firmware Activation: %s\n",
> +                               rc == 0 ? "SUCCESS" : "FAILED");
>                 break;
>         case RESET_ABORT:
> -               pqi_ofa_ctrl_unquiesce(ctrl_info);
>                 dev_info(&ctrl_info->pci_dev->dev,
> -                       "Online Firmware Activation for controller
> %u: %s\n",
> -                       ctrl_info->ctrl_id, "ABORTED");
> +                               "Online Firmware Activation
> ABORTED\n");
> +               if (ctrl_info->soft_reset_handshake_supported)
> +                       pqi_clear_soft_reset_status(ctrl_info);
> +               pqi_ctrl_ofa_done(ctrl_info);
> +               pqi_ofa_ctrl_unquiesce(ctrl_info);
>                 break;
>         case RESET_NORESPONSE:
> -               pqi_ofa_free_host_buffer(ctrl_info);
> +               fallthrough;
> +       default:
> +               dev_err(&ctrl_info->pci_dev->dev,
> +                       "unexpected Online Firmware Activation reset
> status: 0x%x\n",
> +                       reset_status);
> +               pqi_ctrl_ofa_done(ctrl_info);
> +               pqi_ofa_ctrl_unquiesce(ctrl_info);
>                 pqi_take_ctrl_offline(ctrl_info);
>                 break;
>         }
>  }
>
> -static void pqi_ofa_process_event(struct pqi_ctrl_info *ctrl_info,
> -       struct pqi_event *event)
> +static void pqi_ofa_memory_alloc_worker(struct work_struct *work)

Moving the ofa handling into work queues seems to be a key aspect of
this patch. The patch description should mention how this is will
improve synchronization. Naïve thinking suggests that making these
calls asynchronous could aggravate synchronization issues.

Repeating myself, I feel that completions would be the best way so
synchronize with these work items.

>  {
> -       u16 event_id;
> -       enum pqi_soft_reset_status status;
> +       struct pqi_ctrl_info *ctrl_info;
>
> -       event_id = get_unaligned_le16(&event->event_id);
> +       ctrl_info = container_of(work, struct pqi_ctrl_info,
> ofa_memory_alloc_work);
>
> -       mutex_lock(&ctrl_info->ofa_mutex);
> +       pqi_ctrl_ofa_start(ctrl_info);
> +       pqi_ofa_setup_host_buffer(ctrl_info);
> +       pqi_ofa_host_memory_update(ctrl_info);
> +}
>
> -       if (event_id == PQI_EVENT_OFA_QUIESCE) {
> -               dev_info(&ctrl_info->pci_dev->dev,
> -                       "Received Online Firmware Activation quiesce
> event for controller %u\n",
> -                       ctrl_info->ctrl_id);
> -               pqi_ofa_ctrl_quiesce(ctrl_info);
> -               pqi_acknowledge_event(ctrl_info, event);
> -               if (ctrl_info->soft_reset_handshake_supported) {
> -                       status =
> pqi_poll_for_soft_reset_status(ctrl_info);
> -                       pqi_process_soft_reset(ctrl_info, status);
> -               } else {
> -                       pqi_process_soft_reset(ctrl_info,
> -                                       RESET_INITIATE_FIRMWARE);
> -               }
> +static void pqi_ofa_quiesce_worker(struct work_struct *work)
> +{
> +       struct pqi_ctrl_info *ctrl_info;
> +       struct pqi_event *event;
>
> -       } else if (event_id == PQI_EVENT_OFA_MEMORY_ALLOCATION) {
> -               pqi_acknowledge_event(ctrl_info, event);
> -               pqi_ofa_setup_host_buffer(ctrl_info,
> -                       le32_to_cpu(event->ofa_bytes_requested));
> -               pqi_ofa_host_memory_update(ctrl_info);
> -       } else if (event_id == PQI_EVENT_OFA_CANCELED) {
> -               pqi_ofa_free_host_buffer(ctrl_info);
> -               pqi_acknowledge_event(ctrl_info, event);
> +       ctrl_info = container_of(work, struct pqi_ctrl_info,
> ofa_quiesce_work);
> +
> +       event = &ctrl_info-
> >events[pqi_event_type_to_event_index(PQI_EVENT_TYPE_OFA)];
> +
> +       pqi_ofa_ctrl_quiesce(ctrl_info);
> +       pqi_acknowledge_event(ctrl_info, event);
> +       pqi_process_soft_reset(ctrl_info);
> +}
> +
> +static bool pqi_ofa_process_event(struct pqi_ctrl_info *ctrl_info,
> +       struct pqi_event *event)
> +{
> +       bool ack_event;
> +
> +       ack_event = true;
> +
> +       switch (event->event_id) {
> +       case PQI_EVENT_OFA_MEMORY_ALLOCATION:
> +               dev_info(&ctrl_info->pci_dev->dev,
> +                       "received Online Firmware Activation memory
> allocation request\n");
> +               schedule_work(&ctrl_info->ofa_memory_alloc_work);
> +               break;
> +       case PQI_EVENT_OFA_QUIESCE:
>                 dev_info(&ctrl_info->pci_dev->dev,
> -                       "Online Firmware Activation(%u) cancel reason
> : %u\n",
> -                       ctrl_info->ctrl_id, event-
> >ofa_cancel_reason);
> +                       "received Online Firmware Activation quiesce
> request\n");
> +               schedule_work(&ctrl_info->ofa_quiesce_work);
> +               ack_event = false;
> +               break;
> +       case PQI_EVENT_OFA_CANCELED:
> +               dev_info(&ctrl_info->pci_dev->dev,
> +                       "received Online Firmware Activation cancel
> request: reason: %u\n",
> +                       ctrl_info->ofa_cancel_reason);
> +               pqi_ofa_free_host_buffer(ctrl_info);
> +               pqi_ctrl_ofa_done(ctrl_info);
> +               break;
> +       default:
> +               dev_err(&ctrl_info->pci_dev->dev,
> +                       "received unknown Online Firmware Activation
> request: event ID: %u\n",
> +                       event->event_id);
> +               break;
>         }
>
> -       mutex_unlock(&ctrl_info->ofa_mutex);
> +       return ack_event;
>  }
>
>  static void pqi_event_worker(struct work_struct *work)
>  {
>         unsigned int i;
> +       bool rescan_needed;
>         struct pqi_ctrl_info *ctrl_info;
>         struct pqi_event *event;
> +       bool ack_event;
>
>         ctrl_info = container_of(work, struct pqi_ctrl_info,
> event_work);
>
>         pqi_ctrl_busy(ctrl_info);
> -       pqi_wait_if_ctrl_blocked(ctrl_info, NO_TIMEOUT);
> +       pqi_wait_if_ctrl_blocked(ctrl_info);
>         if (pqi_ctrl_offline(ctrl_info))
>                 goto out;
>
> -       pqi_schedule_rescan_worker_delayed(ctrl_info);
> -
> +       rescan_needed = false;
>         event = ctrl_info->events;
>         for (i = 0; i < PQI_NUM_SUPPORTED_EVENTS; i++) {
>                 if (event->pending) {
>                         event->pending = false;
>                         if (event->event_type == PQI_EVENT_TYPE_OFA)
> {
> -                               pqi_ctrl_unbusy(ctrl_info);
> -                               pqi_ofa_process_event(ctrl_info,
> event);
> -                               return;
> +                               ack_event =
> pqi_ofa_process_event(ctrl_info, event);
> +                       } else {
> +                               ack_event = true;
> +                               rescan_needed = true;
>                         }
> -                       pqi_acknowledge_event(ctrl_info, event);
> +                       if (ack_event)
> +                               pqi_acknowledge_event(ctrl_info,
> event);
>                 }
>                 event++;
>         }
>
> +       if (rescan_needed)
> +               pqi_schedule_rescan_worker_delayed(ctrl_info);
> +
>  out:
>         pqi_ctrl_unbusy(ctrl_info);
>  }
> @@ -3446,37 +3500,18 @@ static inline void
> pqi_stop_heartbeat_timer(struct pqi_ctrl_info *ctrl_info)
>         del_timer_sync(&ctrl_info->heartbeat_timer);
>  }
>
> -static inline int pqi_event_type_to_event_index(unsigned int
> event_type)
> -{
> -       int index;
> -
> -       for (index = 0; index <
> ARRAY_SIZE(pqi_supported_event_types); index++)
> -               if (event_type == pqi_supported_event_types[index])
> -                       return index;
> -
> -       return -1;
> -}
> -
> -static inline bool pqi_is_supported_event(unsigned int event_type)
> -{
> -       return pqi_event_type_to_event_index(event_type) != -1;
> -}
> -
> -static void pqi_ofa_capture_event_payload(struct pqi_event *event,
> -       struct pqi_event_response *response)
> +static void pqi_ofa_capture_event_payload(struct pqi_ctrl_info
> *ctrl_info,
> +       struct pqi_event *event, struct pqi_event_response *response)
>  {
> -       u16 event_id;
> -
> -       event_id = get_unaligned_le16(&event->event_id);
> -
> -       if (event->event_type == PQI_EVENT_TYPE_OFA) {
> -               if (event_id == PQI_EVENT_OFA_MEMORY_ALLOCATION) {
> -                       event->ofa_bytes_requested =
> -                       response-
> >data.ofa_memory_allocation.bytes_requested;
> -               } else if (event_id == PQI_EVENT_OFA_CANCELED) {
> -                       event->ofa_cancel_reason =
> -                       response->data.ofa_cancelled.reason;
> -               }
> +       switch (event->event_id) {
> +       case PQI_EVENT_OFA_MEMORY_ALLOCATION:
> +               ctrl_info->ofa_bytes_requested =
> +                       get_unaligned_le32(&response-
> >data.ofa_memory_allocation.bytes_requested);
> +               break;
> +       case PQI_EVENT_OFA_CANCELED:
> +               ctrl_info->ofa_cancel_reason =
> +                       get_unaligned_le16(&response-
> >data.ofa_cancelled.reason);
> +               break;
>         }
>  }
>
> @@ -3510,17 +3545,17 @@ static int pqi_process_event_intr(struct
> pqi_ctrl_info *ctrl_info)
>                 num_events++;
>                 response = event_queue->oq_element_array + (oq_ci *
> PQI_EVENT_OQ_ELEMENT_LENGTH);
>
> -               event_index =
> -                       pqi_event_type_to_event_index(response-
> >event_type);
> +               event_index = pqi_event_type_to_event_index(response-
> >event_type);
>
>                 if (event_index >= 0 && response-
> >request_acknowledge) {
>                         event = &ctrl_info->events[event_index];
>                         event->pending = true;
>                         event->event_type = response->event_type;
> -                       event->event_id = response->event_id;
> -                       event->additional_event_id = response-
> >additional_event_id;
> +                       event->event_id =
> get_unaligned_le16(&response->event_id);
> +                       event->additional_event_id =
> +                               get_unaligned_le32(&response-
> >additional_event_id);
>                         if (event->event_type == PQI_EVENT_TYPE_OFA)
> -                               pqi_ofa_capture_event_payload(event,
> response);
> +                               pqi_ofa_capture_event_payload(ctrl_in
> fo, event, response);
>                 }
>
>                 oq_ci = (oq_ci + 1) % PQI_NUM_EVENT_QUEUE_ELEMENTS;
> @@ -3537,8 +3572,7 @@ static int pqi_process_event_intr(struct
> pqi_ctrl_info *ctrl_info)
>
>  #define PQI_LEGACY_INTX_MASK   0x1
>
> -static inline void pqi_configure_legacy_intx(struct pqi_ctrl_info
> *ctrl_info,
> -       bool enable_intx)
> +static inline void pqi_configure_legacy_intx(struct pqi_ctrl_info
> *ctrl_info, bool enable_intx)

another whitespace hunk

>  {
>         u32 intx_mask;
>         struct pqi_device_registers __iomem *pqi_registers;
> @@ -4216,59 +4250,36 @@ static int
> pqi_process_raid_io_error_synchronous(
>         return rc;
>  }
>
> +static inline bool pqi_is_blockable_request(struct pqi_iu_header
> *request)
> +{
> +       return (request->driver_flags &
> PQI_DRIVER_NONBLOCKABLE_REQUEST) == 0;
> +}
> +
>  static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info
> *ctrl_info,
>         struct pqi_iu_header *request, unsigned int flags,
> -       struct pqi_raid_error_info *error_info, unsigned long
> timeout_msecs)
> +       struct pqi_raid_error_info *error_info)

The removal of the timeout_msecs argument to this function could be
a separate patch in its own right.

>  {
>         int rc = 0;
>         struct pqi_io_request *io_request;
> -       unsigned long start_jiffies;
> -       unsigned long msecs_blocked;
>         size_t iu_length;
>         DECLARE_COMPLETION_ONSTACK(wait);
>
> -       /*
> -        * Note that specifying PQI_SYNC_FLAGS_INTERRUPTABLE and a
> timeout value
> -        * are mutually exclusive.
> -        */
> -
>         if (flags & PQI_SYNC_FLAGS_INTERRUPTABLE) {
>                 if (down_interruptible(&ctrl_info->sync_request_sem))
>                         return -ERESTARTSYS;
>         } else {
> -               if (timeout_msecs == NO_TIMEOUT) {
> -                       down(&ctrl_info->sync_request_sem);
> -               } else {
> -                       start_jiffies = jiffies;
> -                       if (down_timeout(&ctrl_info-
> >sync_request_sem,
> -                               msecs_to_jiffies(timeout_msecs)))
> -                               return -ETIMEDOUT;
> -                       msecs_blocked =
> -                               jiffies_to_msecs(jiffies -
> start_jiffies);
> -                       if (msecs_blocked >= timeout_msecs) {
> -                               rc = -ETIMEDOUT;
> -                               goto out;
> -                       }
> -                       timeout_msecs -= msecs_blocked;
> -               }
> +               down(&ctrl_info->sync_request_sem);
>         }
>
>         pqi_ctrl_busy(ctrl_info);
> -       timeout_msecs = pqi_wait_if_ctrl_blocked(ctrl_info,
> timeout_msecs);
> -       if (timeout_msecs == 0) {
> -               pqi_ctrl_unbusy(ctrl_info);
> -               rc = -ETIMEDOUT;
> -               goto out;
> -       }
> +       if (pqi_is_blockable_request(request))
> +               pqi_wait_if_ctrl_blocked(ctrl_info);

You wait here after taking the semaphore - is that intended? Why?

>
>         if (pqi_ctrl_offline(ctrl_info)) {

Should you test this before waiting, perhaps?

> -               pqi_ctrl_unbusy(ctrl_info);
>                 rc = -ENXIO;
>                 goto out;
>         }
>
> -       atomic_inc(&ctrl_info->sync_cmds_outstanding);
> -
>         io_request = pqi_alloc_io_request(ctrl_info);
>
>         put_unaligned_le16(io_request->index,
> @@ -4288,18 +4299,7 @@ static int
> pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
>         pqi_start_io(ctrl_info, &ctrl_info-
> >queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH,
>                 io_request);
>
> -       pqi_ctrl_unbusy(ctrl_info);
> -
> -       if (timeout_msecs == NO_TIMEOUT) {
> -               pqi_wait_for_completion_io(ctrl_info, &wait);
> -       } else {
> -               if (!wait_for_completion_io_timeout(&wait,
> -                       msecs_to_jiffies(timeout_msecs))) {
> -                       dev_warn(&ctrl_info->pci_dev->dev,
> -                               "command timed out\n");
> -                       rc = -ETIMEDOUT;
> -               }
> -       }
> +       pqi_wait_for_completion_io(ctrl_info, &wait);
>
>         if (error_info) {
>                 if (io_request->error_info)
> @@ -4312,8 +4312,8 @@ static int
> pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
>
>         pqi_free_io_request(io_request);
>
> -       atomic_dec(&ctrl_info->sync_cmds_outstanding);
>  out:
> +       pqi_ctrl_unbusy(ctrl_info);
>         up(&ctrl_info->sync_request_sem);
>
>         return rc;
> @@ -4350,8 +4350,7 @@ static int
> pqi_submit_admin_request_synchronous(
>         rc = pqi_poll_for_admin_response(ctrl_info, response);
>
>         if (rc == 0)
> -               rc = pqi_validate_admin_response(response,
> -                       request->function_code);
> +               rc = pqi_validate_admin_response(response, request-
> >function_code);
>
>         return rc;
>  }
> @@ -4721,7 +4720,7 @@ static int pqi_configure_events(struct
> pqi_ctrl_info *ctrl_info,
>                 goto out;
>
>         rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header,
> -               0, NULL, NO_TIMEOUT);
> +               0, NULL);
>
>         pqi_pci_unmap(ctrl_info->pci_dev,
>                 request.data.report_event_configuration.sg_descriptor
> s, 1,
> @@ -4757,7 +4756,7 @@ static int pqi_configure_events(struct
> pqi_ctrl_info *ctrl_info,
>                 goto out;
>
>         rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header, 0,
> -               NULL, NO_TIMEOUT);
> +               NULL);
>
>         pqi_pci_unmap(ctrl_info->pci_dev,
>                 request.data.report_event_configuration.sg_descriptor
> s, 1,
> @@ -5277,12 +5276,6 @@ static inline int
> pqi_raid_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info,
>                 device, scmd, queue_group);
>  }
>

Below here, a new section starts that refacors the treatment of bypass
retries. I don't see how this is related to the synchronization issues
mentioned in the patch description.


> -static inline void pqi_schedule_bypass_retry(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       if (!pqi_ctrl_blocked(ctrl_info))
> -               schedule_work(&ctrl_info->raid_bypass_retry_work);
> -}
> -
>  static bool pqi_raid_bypass_retry_needed(struct pqi_io_request
> *io_request)
>  {
>         struct scsi_cmnd *scmd;
> @@ -5299,7 +5292,7 @@ static bool pqi_raid_bypass_retry_needed(struct
> pqi_io_request *io_request)
>                 return false;
>
>         device = scmd->device->hostdata;
> -       if (pqi_device_offline(device))
> +       if (pqi_device_offline(device) ||
> pqi_device_in_remove(device))
>                 return false;
>
>         ctrl_info = shost_to_hba(scmd->device->host);
> @@ -5309,155 +5302,26 @@ static bool
> pqi_raid_bypass_retry_needed(struct pqi_io_request *io_request)
>         return true;
>  }
>
> -static inline void pqi_add_to_raid_bypass_retry_list(
> -       struct pqi_ctrl_info *ctrl_info,
> -       struct pqi_io_request *io_request, bool at_head)
> -{
> -       unsigned long flags;
> -
> -       spin_lock_irqsave(&ctrl_info->raid_bypass_retry_list_lock,
> flags);
> -       if (at_head)
> -               list_add(&io_request->request_list_entry,
> -                       &ctrl_info->raid_bypass_retry_list);
> -       else
> -               list_add_tail(&io_request->request_list_entry,
> -                       &ctrl_info->raid_bypass_retry_list);
> -       spin_unlock_irqrestore(&ctrl_info-
> >raid_bypass_retry_list_lock, flags);
> -}
> -
> -static void pqi_queued_raid_bypass_complete(struct pqi_io_request
> *io_request,
> +static void pqi_aio_io_complete(struct pqi_io_request *io_request,
>         void *context)
>  {
>         struct scsi_cmnd *scmd;
>
>         scmd = io_request->scmd;
> +       scsi_dma_unmap(scmd);
> +       if (io_request->status == -EAGAIN ||
> +               pqi_raid_bypass_retry_needed(io_request))
> +                       set_host_byte(scmd, DID_IMM_RETRY);
>         pqi_free_io_request(io_request);
>         pqi_scsi_done(scmd);
>  }
>
> -static void pqi_queue_raid_bypass_retry(struct pqi_io_request
> *io_request)
> +static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info
> *ctrl_info,
> +       struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
> +       struct pqi_queue_group *queue_group)
>  {
> -       struct scsi_cmnd *scmd;
> -       struct pqi_ctrl_info *ctrl_info;
> -
> -       io_request->io_complete_callback =
> pqi_queued_raid_bypass_complete;
> -       scmd = io_request->scmd;
> -       scmd->result = 0;
> -       ctrl_info = shost_to_hba(scmd->device->host);
> -
> -       pqi_add_to_raid_bypass_retry_list(ctrl_info, io_request,
> false);
> -       pqi_schedule_bypass_retry(ctrl_info);
> -}
> -
> -static int pqi_retry_raid_bypass(struct pqi_io_request *io_request)
> -{
> -       struct scsi_cmnd *scmd;
> -       struct pqi_scsi_dev *device;
> -       struct pqi_ctrl_info *ctrl_info;
> -       struct pqi_queue_group *queue_group;
> -
> -       scmd = io_request->scmd;
> -       device = scmd->device->hostdata;
> -       if (pqi_device_in_reset(device)) {
> -               pqi_free_io_request(io_request);
> -               set_host_byte(scmd, DID_RESET);
> -               pqi_scsi_done(scmd);
> -               return 0;
> -       }
> -
> -       ctrl_info = shost_to_hba(scmd->device->host);
> -       queue_group = io_request->queue_group;
> -
> -       pqi_reinit_io_request(io_request);
> -
> -       return pqi_raid_submit_scsi_cmd_with_io_request(ctrl_info,
> io_request,
> -               device, scmd, queue_group);
> -}
> -
> -static inline struct pqi_io_request
> *pqi_next_queued_raid_bypass_request(
> -       struct pqi_ctrl_info *ctrl_info)
> -{
> -       unsigned long flags;
> -       struct pqi_io_request *io_request;
> -
> -       spin_lock_irqsave(&ctrl_info->raid_bypass_retry_list_lock,
> flags);
> -       io_request = list_first_entry_or_null(
> -               &ctrl_info->raid_bypass_retry_list,
> -               struct pqi_io_request, request_list_entry);
> -       if (io_request)
> -               list_del(&io_request->request_list_entry);
> -       spin_unlock_irqrestore(&ctrl_info-
> >raid_bypass_retry_list_lock, flags);
> -
> -       return io_request;
> -}
> -
> -static void pqi_retry_raid_bypass_requests(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       int rc;
> -       struct pqi_io_request *io_request;
> -
> -       pqi_ctrl_busy(ctrl_info);
> -
> -       while (1) {
> -               if (pqi_ctrl_blocked(ctrl_info))
> -                       break;
> -               io_request =
> pqi_next_queued_raid_bypass_request(ctrl_info);
> -               if (!io_request)
> -                       break;
> -               rc = pqi_retry_raid_bypass(io_request);
> -               if (rc) {
> -                       pqi_add_to_raid_bypass_retry_list(ctrl_info,
> io_request,
> -                               true);
> -                       pqi_schedule_bypass_retry(ctrl_info);
> -                       break;
> -               }
> -       }
> -
> -       pqi_ctrl_unbusy(ctrl_info);
> -}
> -
> -static void pqi_raid_bypass_retry_worker(struct work_struct *work)
> -{
> -       struct pqi_ctrl_info *ctrl_info;
> -
> -       ctrl_info = container_of(work, struct pqi_ctrl_info,
> -               raid_bypass_retry_work);
> -       pqi_retry_raid_bypass_requests(ctrl_info);
> -}
> -
> -static void pqi_clear_all_queued_raid_bypass_retries(
> -       struct pqi_ctrl_info *ctrl_info)
> -{
> -       unsigned long flags;
> -
> -       spin_lock_irqsave(&ctrl_info->raid_bypass_retry_list_lock,
> flags);
> -       INIT_LIST_HEAD(&ctrl_info->raid_bypass_retry_list);
> -       spin_unlock_irqrestore(&ctrl_info-
> >raid_bypass_retry_list_lock, flags);
> -}
> -
> -static void pqi_aio_io_complete(struct pqi_io_request *io_request,
> -       void *context)
> -{
> -       struct scsi_cmnd *scmd;
> -
> -       scmd = io_request->scmd;
> -       scsi_dma_unmap(scmd);
> -       if (io_request->status == -EAGAIN)
> -               set_host_byte(scmd, DID_IMM_RETRY);
> -       else if (pqi_raid_bypass_retry_needed(io_request)) {
> -               pqi_queue_raid_bypass_retry(io_request);
> -               return;
> -       }
> -       pqi_free_io_request(io_request);
> -       pqi_scsi_done(scmd);
> -}
> -
> -static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info
> *ctrl_info,
> -       struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
> -       struct pqi_queue_group *queue_group)
> -{
> -       return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle,
> -               scmd->cmnd, scmd->cmd_len, queue_group, NULL, false);
> +       return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle,
> +               scmd->cmnd, scmd->cmd_len, queue_group, NULL, false);
>  }
>
>  static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info,
> @@ -5698,6 +5562,14 @@ static inline u16 pqi_get_hw_queue(struct
> pqi_ctrl_info *ctrl_info,
>         return hw_queue;
>  }
>
> +static inline bool pqi_is_bypass_eligible_request(struct scsi_cmnd
> *scmd)
> +{
> +       if (blk_rq_is_passthrough(scmd->request))
> +               return false;
> +
> +       return scmd->retries == 0;
> +}
> +

Nice, but this fits better into (or next to) 10/25 IMO.

>  /*
>   * This function gets called just before we hand the completed SCSI
> request
>   * back to the SML.
> @@ -5806,7 +5678,6 @@ static int pqi_scsi_queue_command(struct
> Scsi_Host *shost, struct scsi_cmnd *scm
>         bool raid_bypassed;
>
>         device = scmd->device->hostdata;
> -       ctrl_info = shost_to_hba(shost);
>
>         if (!device) {
>                 set_host_byte(scmd, DID_NO_CONNECT);
> @@ -5816,15 +5687,15 @@ static int pqi_scsi_queue_command(struct
> Scsi_Host *shost, struct scsi_cmnd *scm
>
>         atomic_inc(&device->scsi_cmds_outstanding);
>
> +       ctrl_info = shost_to_hba(shost);
> +
>         if (pqi_ctrl_offline(ctrl_info) ||
> pqi_device_in_remove(device)) {
>                 set_host_byte(scmd, DID_NO_CONNECT);
>                 pqi_scsi_done(scmd);
>                 return 0;
>         }
>
> -       pqi_ctrl_busy(ctrl_info);
> -       if (pqi_ctrl_blocked(ctrl_info) ||
> pqi_device_in_reset(device) ||
> -           pqi_ctrl_in_ofa(ctrl_info) ||
> pqi_ctrl_in_shutdown(ctrl_info)) {
> +       if (pqi_ctrl_blocked(ctrl_info)) {
>                 rc = SCSI_MLQUEUE_HOST_BUSY;
>                 goto out;
>         }
> @@ -5841,13 +5712,12 @@ static int pqi_scsi_queue_command(struct
> Scsi_Host *shost, struct scsi_cmnd *scm
>         if (pqi_is_logical_device(device)) {
>                 raid_bypassed = false;
>                 if (device->raid_bypass_enabled &&
> -                       !blk_rq_is_passthrough(scmd->request)) {
> -                       if (!pqi_is_parity_write_stream(ctrl_info,
> scmd)) {
> -                               rc =
> pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd,
> queue_group);
> -                               if (rc == 0 || rc ==
> SCSI_MLQUEUE_HOST_BUSY) {
> -                                       raid_bypassed = true;
> -                                       atomic_inc(&device-
> >raid_bypass_cnt);
> -                               }
> +                       pqi_is_bypass_eligible_request(scmd) &&
> +                       !pqi_is_parity_write_stream(ctrl_info, scmd))
> {
> +                       rc =
> pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd,
> queue_group);
> +                       if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY)
> {
> +                               raid_bypassed = true;
> +                               atomic_inc(&device->raid_bypass_cnt);
>                         }
>                 }
>                 if (!raid_bypassed)
> @@ -5860,7 +5730,6 @@ static int pqi_scsi_queue_command(struct
> Scsi_Host *shost, struct scsi_cmnd *scm
>         }
>
>  out:
> -       pqi_ctrl_unbusy(ctrl_info);
>         if (rc)
>                 atomic_dec(&device->scsi_cmds_outstanding);
>
> @@ -5970,100 +5839,22 @@ static void
> pqi_fail_io_queued_for_device(struct pqi_ctrl_info *ctrl_info,
>         }
>  }
>
> -static void pqi_fail_io_queued_for_all_devices(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       unsigned int i;
> -       unsigned int path;
> -       struct pqi_queue_group *queue_group;
> -       unsigned long flags;
> -       struct pqi_io_request *io_request;
> -       struct pqi_io_request *next;
> -       struct scsi_cmnd *scmd;
> -
> -       for (i = 0; i < ctrl_info->num_queue_groups; i++) {
> -               queue_group = &ctrl_info->queue_groups[i];
> -
> -               for (path = 0; path < 2; path++) {
> -                       spin_lock_irqsave(&queue_group-
> >submit_lock[path],
> -                                               flags);
> -
> -                       list_for_each_entry_safe(io_request, next,
> -                               &queue_group->request_list[path],
> -                               request_list_entry) {
> -
> -                               scmd = io_request->scmd;
> -                               if (!scmd)
> -                                       continue;
> -
> -                               list_del(&io_request-
> >request_list_entry);
> -                               set_host_byte(scmd, DID_RESET);
> -                               pqi_scsi_done(scmd);
> -                       }
> -
> -                       spin_unlock_irqrestore(
> -                               &queue_group->submit_lock[path],
> flags);
> -               }
> -       }
> -}
> -
>  static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info
> *ctrl_info,
>         struct pqi_scsi_dev *device, unsigned long timeout_secs)
>  {
>         unsigned long timeout;
>
> -       timeout = (timeout_secs * PQI_HZ) + jiffies;
> -
> -       while (atomic_read(&device->scsi_cmds_outstanding)) {
> -               pqi_check_ctrl_health(ctrl_info);
> -               if (pqi_ctrl_offline(ctrl_info))
> -                       return -ENXIO;
> -               if (timeout_secs != NO_TIMEOUT) {
> -                       if (time_after(jiffies, timeout)) {
> -                               dev_err(&ctrl_info->pci_dev->dev,
> -                                       "timed out waiting for
> pending IO\n");
> -                               return -ETIMEDOUT;
> -                       }
> -               }
> -               usleep_range(1000, 2000);
> -       }
> -
> -       return 0;
> -}
> -
> -static int pqi_ctrl_wait_for_pending_io(struct pqi_ctrl_info
> *ctrl_info,
> -       unsigned long timeout_secs)
> -{
> -       bool io_pending;
> -       unsigned long flags;
> -       unsigned long timeout;
> -       struct pqi_scsi_dev *device;
>
>         timeout = (timeout_secs * PQI_HZ) + jiffies;
> -       while (1) {
> -               io_pending = false;
> -
> -               spin_lock_irqsave(&ctrl_info->scsi_device_list_lock,
> flags);
> -               list_for_each_entry(device, &ctrl_info-
> >scsi_device_list,
> -                       scsi_device_list_entry) {
> -                       if (atomic_read(&device-
> >scsi_cmds_outstanding)) {
> -                               io_pending = true;
> -                               break;
> -                       }
> -               }
> -               spin_unlock_irqrestore(&ctrl_info-
> >scsi_device_list_lock,
> -                                       flags);
> -
> -               if (!io_pending)
> -                       break;
>
> +       while (atomic_read(&device->scsi_cmds_outstanding)) {
>                 pqi_check_ctrl_health(ctrl_info);
>                 if (pqi_ctrl_offline(ctrl_info))
>                         return -ENXIO;
> -
>                 if (timeout_secs != NO_TIMEOUT) {
>                         if (time_after(jiffies, timeout)) {
>                                 dev_err(&ctrl_info->pci_dev->dev,
> -                                       "timed out waiting for
> pending IO\n");
> +                                       "timed out waiting for
> pending I/O\n");
>                                 return -ETIMEDOUT;
>                         }
>                 }

Like I said above (wrt pqi_scsi_block_requests), have you considered
using wait_event_timeout() here?


> @@ -6073,18 +5864,6 @@ static int pqi_ctrl_wait_for_pending_io(struct
> pqi_ctrl_info *ctrl_info,
>         return 0;
>  }
>
> -static int pqi_ctrl_wait_for_pending_sync_cmds(struct pqi_ctrl_info
> *ctrl_info)
> -{
> -       while (atomic_read(&ctrl_info->sync_cmds_outstanding)) {
> -               pqi_check_ctrl_health(ctrl_info);
> -               if (pqi_ctrl_offline(ctrl_info))
> -                       return -ENXIO;
> -               usleep_range(1000, 2000);
> -       }
> -
> -       return 0;
> -}
> -
>  static void pqi_lun_reset_complete(struct pqi_io_request
> *io_request,
>         void *context)
>  {
> @@ -6156,13 +5935,11 @@ static int pqi_lun_reset(struct pqi_ctrl_info
> *ctrl_info,
>         return rc;
>  }
>
> -/* Performs a reset at the LUN level. */
> -
>  #define PQI_LUN_RESET_RETRIES                  3
>  #define PQI_LUN_RESET_RETRY_INTERVAL_MSECS     10000
>  #define PQI_LUN_RESET_PENDING_IO_TIMEOUT_SECS  120
>
> -static int _pqi_device_reset(struct pqi_ctrl_info *ctrl_info,
> +static int pqi_lun_reset_with_retries(struct pqi_ctrl_info
> *ctrl_info,
>         struct pqi_scsi_dev *device)
>  {
>         int rc;
> @@ -6188,23 +5965,15 @@ static int pqi_device_reset(struct
> pqi_ctrl_info *ctrl_info,
>  {
>         int rc;
>
> -       mutex_lock(&ctrl_info->lun_reset_mutex);
> -
>         pqi_ctrl_block_requests(ctrl_info);
>         pqi_ctrl_wait_until_quiesced(ctrl_info);
>         pqi_fail_io_queued_for_device(ctrl_info, device);
>         rc = pqi_wait_until_inbound_queues_empty(ctrl_info);
> -       pqi_device_reset_start(device);
> -       pqi_ctrl_unblock_requests(ctrl_info);
> -
>         if (rc)
>                 rc = FAILED;
>         else
> -               rc = _pqi_device_reset(ctrl_info, device);
> -
> -       pqi_device_reset_done(device);
> -
> -       mutex_unlock(&ctrl_info->lun_reset_mutex);
> +               rc = pqi_lun_reset_with_retries(ctrl_info, device);
> +       pqi_ctrl_unblock_requests(ctrl_info);
>
>         return rc;
>  }
> @@ -6220,29 +5989,25 @@ static int pqi_eh_device_reset_handler(struct
> scsi_cmnd *scmd)
>         ctrl_info = shost_to_hba(shost);
>         device = scmd->device->hostdata;
>
> +       mutex_lock(&ctrl_info->lun_reset_mutex);
> +
>         dev_err(&ctrl_info->pci_dev->dev,
>                 "resetting scsi %d:%d:%d:%d\n",
>                 shost->host_no, device->bus, device->target, device-
> >lun);
>
>         pqi_check_ctrl_health(ctrl_info);
> -       if (pqi_ctrl_offline(ctrl_info) ||
> -               pqi_device_reset_blocked(ctrl_info)) {
> +       if (pqi_ctrl_offline(ctrl_info))
>                 rc = FAILED;
> -               goto out;
> -       }
> -
> -       pqi_wait_until_ofa_finished(ctrl_info);
> -
> -       atomic_inc(&ctrl_info->sync_cmds_outstanding);
> -       rc = pqi_device_reset(ctrl_info, device);
> -       atomic_dec(&ctrl_info->sync_cmds_outstanding);
> +       else
> +               rc = pqi_device_reset(ctrl_info, device);
>
> -out:
>         dev_err(&ctrl_info->pci_dev->dev,
>                 "reset of scsi %d:%d:%d:%d: %s\n",
>                 shost->host_no, device->bus, device->target, device-
> >lun,
>                 rc == SUCCESS ? "SUCCESS" : "FAILED");
>
> +       mutex_unlock(&ctrl_info->lun_reset_mutex);
> +
>         return rc;
>  }
>
> @@ -6544,7 +6309,7 @@ static int pqi_passthru_ioctl(struct
> pqi_ctrl_info *ctrl_info, void __user *arg)
>                 put_unaligned_le32(iocommand.Request.Timeout,
> &request.timeout);
>
>         rc = pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header,
> -               PQI_SYNC_FLAGS_INTERRUPTABLE, &pqi_error_info,
> NO_TIMEOUT);
> +               PQI_SYNC_FLAGS_INTERRUPTABLE, &pqi_error_info);
>
>         if (iocommand.buf_size > 0)
>                 pqi_pci_unmap(ctrl_info->pci_dev,
> request.sg_descriptors, 1,
> @@ -6596,9 +6361,6 @@ static int pqi_ioctl(struct scsi_device *sdev,
> unsigned int cmd,
>
>         ctrl_info = shost_to_hba(sdev->host);
>
> -       if (pqi_ctrl_in_ofa(ctrl_info) ||
> pqi_ctrl_in_shutdown(ctrl_info))
> -               return -EBUSY;
> -
>         switch (cmd) {
>         case CCISS_DEREGDISK:
>         case CCISS_REGNEWDISK:
> @@ -7145,9 +6907,7 @@ static int pqi_register_scsi(struct
> pqi_ctrl_info *ctrl_info)
>
>         shost = scsi_host_alloc(&pqi_driver_template,
> sizeof(ctrl_info));
>         if (!shost) {
> -               dev_err(&ctrl_info->pci_dev->dev,
> -                       "scsi_host_alloc failed for controller %u\n",
> -                       ctrl_info->ctrl_id);
> +               dev_err(&ctrl_info->pci_dev->dev, "scsi_host_alloc
> failed\n");
>                 return -ENOMEM;
>         }
>
> @@ -7405,7 +7165,7 @@ static int pqi_config_table_update(struct
> pqi_ctrl_info *ctrl_info,
>                 &request.data.config_table_update.last_section);
>
>         return pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header,
> -               0, NULL, NO_TIMEOUT);
> +               0, NULL);
>  }
>
>  static int pqi_enable_firmware_features(struct pqi_ctrl_info
> *ctrl_info,
> @@ -7483,7 +7243,8 @@ static void
> pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info,
>                 break;
>         case PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE:
>                 ctrl_info->soft_reset_handshake_supported =
> -                       firmware_feature->enabled;
> +                       firmware_feature->enabled &&
> +                       ctrl_info->soft_reset_status;

Should you use readb(ctrl_info->soft_reset_status) here, like above?

>                 break;
>         case PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT:
>                 ctrl_info->raid_iu_timeout_supported =
> firmware_feature->enabled;
> @@ -7491,6 +7252,10 @@ static void
> pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info,
>         case PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT:
>                 ctrl_info->tmf_iu_timeout_supported =
> firmware_feature->enabled;
>                 break;
> +       case PQI_FIRMWARE_FEATURE_UNIQUE_WWID_IN_REPORT_PHYS_LUN:
> +               ctrl_info->unique_wwid_in_report_phys_lun_supported =
> +                       firmware_feature->enabled;
> +               break;
>         }
>
>         pqi_firmware_feature_status(ctrl_info, firmware_feature);
> @@ -7581,6 +7346,11 @@ static struct pqi_firmware_feature
> pqi_firmware_features[] = {
>                 .feature_bit =
> PQI_FIRMWARE_FEATURE_RAID_BYPASS_ON_ENCRYPTED_NVME,
>                 .feature_status = pqi_firmware_feature_status,
>         },
> +       {
> +               .feature_name = "Unique WWID in Report Physical LUN",
> +               .feature_bit =
> PQI_FIRMWARE_FEATURE_UNIQUE_WWID_IN_REPORT_PHYS_LUN,
> +               .feature_status = pqi_ctrl_update_feature_flags,
> +       },
>  };
>
>  static void pqi_process_firmware_features(
> @@ -7665,14 +7435,34 @@ static void
> pqi_process_firmware_features_section(
>         mutex_unlock(&pqi_firmware_features_mutex);
>  }
>

The hunks below look like yet another independent change.
(Handling of firmware_feature_section_present).

> +/*
> + * Reset all controller settings that can be initialized during the
> processing
> + * of the PQI Configuration Table.
> + */
> +
> +static void pqi_ctrl_reset_config(struct pqi_ctrl_info *ctrl_info)
> +{
> +       ctrl_info->heartbeat_counter = NULL;
> +       ctrl_info->soft_reset_status = NULL;
> +       ctrl_info->soft_reset_handshake_supported = false;
> +       ctrl_info->enable_r1_writes = false;
> +       ctrl_info->enable_r5_writes = false;
> +       ctrl_info->enable_r6_writes = false;
> +       ctrl_info->raid_iu_timeout_supported = false;
> +       ctrl_info->tmf_iu_timeout_supported = false;
> +       ctrl_info->unique_wwid_in_report_phys_lun_supported = false;
> +}
> +
>  static int pqi_process_config_table(struct pqi_ctrl_info *ctrl_info)
>  {
>         u32 table_length;
>         u32 section_offset;
> +       bool firmware_feature_section_present;
>         void __iomem *table_iomem_addr;
>         struct pqi_config_table *config_table;
>         struct pqi_config_table_section_header *section;
>         struct pqi_config_table_section_info section_info;
> +       struct pqi_config_table_section_info feature_section_info;
>
>         table_length = ctrl_info->config_table_length;
>         if (table_length == 0)
> @@ -7692,6 +7482,7 @@ static int pqi_process_config_table(struct
> pqi_ctrl_info *ctrl_info)
>         table_iomem_addr = ctrl_info->iomem_base + ctrl_info-
> >config_table_offset;
>         memcpy_fromio(config_table, table_iomem_addr, table_length);
>
> +       firmware_feature_section_present = false;
>         section_info.ctrl_info = ctrl_info;
>         section_offset = get_unaligned_le32(&config_table-
> >first_section_offset);
>
> @@ -7704,7 +7495,8 @@ static int pqi_process_config_table(struct
> pqi_ctrl_info *ctrl_info)
>
>                 switch (get_unaligned_le16(&section->section_id)) {
>                 case PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES:
> -
>                        pqi_process_firmware_features_section(&section_
> info);
> +                       firmware_feature_section_present = true;
> +                       feature_section_info = section_info;
>                         break;
>                 case PQI_CONFIG_TABLE_SECTION_HEARTBEAT:
>                         if (pqi_disable_heartbeat)
> @@ -7722,13 +7514,21 @@ static int pqi_process_config_table(struct
> pqi_ctrl_info *ctrl_info)
>                                 table_iomem_addr +
>                                 section_offset +
>                                 offsetof(struct
> pqi_config_table_soft_reset,
> -                                               soft_reset_status);
> +                                       soft_reset_status);
>                         break;
>                 }
>
>                 section_offset = get_unaligned_le16(&section-
> >next_section_offset);
>         }
>
> +       /*
> +        * We process the firmware feature section after all other
> sections
> +        * have been processed so that the feature bit callbacks can
> take
> +        * into account the settings configured by other sections.
> +        */
> +       if (firmware_feature_section_present)
> +               pqi_process_firmware_features_section(&feature_sectio
> n_info);
> +
>         kfree(config_table);
>
>         return 0;
> @@ -7776,8 +7576,6 @@ static int pqi_force_sis_mode(struct
> pqi_ctrl_info *ctrl_info)
>         return pqi_revert_to_sis_mode(ctrl_info);
>  }
>
> -#define PQI_POST_RESET_DELAY_B4_MSGU_READY     5000
> -
>  static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
>  {
>         int rc;
> @@ -7785,7 +7583,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info
> *ctrl_info)
>
>         if (reset_devices) {
>                 sis_soft_reset(ctrl_info);
> -               msleep(PQI_POST_RESET_DELAY_B4_MSGU_READY);
> +               msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ);
>         } else {
>                 rc = pqi_force_sis_mode(ctrl_info);
>                 if (rc)
> @@ -8095,6 +7893,8 @@ static int pqi_ctrl_init_resume(struct
> pqi_ctrl_info *ctrl_info)
>         ctrl_info->controller_online = true;
>         pqi_ctrl_unblock_requests(ctrl_info);
>
> +       pqi_ctrl_reset_config(ctrl_info);
> +
>         rc = pqi_process_config_table(ctrl_info);
>         if (rc)
>                 return rc;
> @@ -8140,7 +7940,8 @@ static int pqi_ctrl_init_resume(struct
> pqi_ctrl_info *ctrl_info)
>                 return rc;
>         }
>
> -       pqi_schedule_update_time_worker(ctrl_info);
> +       if (pqi_ofa_in_progress(ctrl_info))
> +               pqi_ctrl_unblock_scan(ctrl_info);
>
>         pqi_scan_scsi_devices(ctrl_info);
>
> @@ -8253,7 +8054,6 @@ static struct pqi_ctrl_info
> *pqi_alloc_ctrl_info(int numa_node)
>
>         INIT_WORK(&ctrl_info->event_work, pqi_event_worker);
>         atomic_set(&ctrl_info->num_interrupts, 0);
> -       atomic_set(&ctrl_info->sync_cmds_outstanding, 0);
>
>         INIT_DELAYED_WORK(&ctrl_info->rescan_work,
> pqi_rescan_worker);
>         INIT_DELAYED_WORK(&ctrl_info->update_time_work,
> pqi_update_time_worker);
> @@ -8261,15 +8061,13 @@ static struct pqi_ctrl_info
> *pqi_alloc_ctrl_info(int numa_node)
>         timer_setup(&ctrl_info->heartbeat_timer,
> pqi_heartbeat_timer_handler, 0);
>         INIT_WORK(&ctrl_info->ctrl_offline_work,
> pqi_ctrl_offline_worker);
>
> +       INIT_WORK(&ctrl_info->ofa_memory_alloc_work,
> pqi_ofa_memory_alloc_worker);
> +       INIT_WORK(&ctrl_info->ofa_quiesce_work,
> pqi_ofa_quiesce_worker);
> +
>         sema_init(&ctrl_info->sync_request_sem,
>                 PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS);
>         init_waitqueue_head(&ctrl_info->block_requests_wait);
>
> -       INIT_LIST_HEAD(&ctrl_info->raid_bypass_retry_list);
> -       spin_lock_init(&ctrl_info->raid_bypass_retry_list_lock);
> -       INIT_WORK(&ctrl_info->raid_bypass_retry_work,
> -               pqi_raid_bypass_retry_worker);
> -
>         ctrl_info->ctrl_id = atomic_inc_return(&pqi_controller_count)
> - 1;
>         ctrl_info->irq_mode = IRQ_MODE_NONE;
>         ctrl_info->max_msix_vectors = PQI_MAX_MSIX_VECTORS;
> @@ -8334,81 +8132,57 @@ static void pqi_remove_ctrl(struct
> pqi_ctrl_info *ctrl_info)
>
>  static void pqi_ofa_ctrl_quiesce(struct pqi_ctrl_info *ctrl_info)
>  {
> -       pqi_cancel_update_time_worker(ctrl_info);
> -       pqi_cancel_rescan_worker(ctrl_info);
> -       pqi_wait_until_lun_reset_finished(ctrl_info);
> -       pqi_wait_until_scan_finished(ctrl_info);
> -       pqi_ctrl_ofa_start(ctrl_info);
> +       pqi_ctrl_block_scan(ctrl_info);
> +       pqi_scsi_block_requests(ctrl_info);
> +       pqi_ctrl_block_device_reset(ctrl_info);
>         pqi_ctrl_block_requests(ctrl_info);
>         pqi_ctrl_wait_until_quiesced(ctrl_info);
> -       pqi_ctrl_wait_for_pending_io(ctrl_info,
> PQI_PENDING_IO_TIMEOUT_SECS);
> -       pqi_fail_io_queued_for_all_devices(ctrl_info);
> -       pqi_wait_until_inbound_queues_empty(ctrl_info);
>         pqi_stop_heartbeat_timer(ctrl_info);
> -       ctrl_info->pqi_mode_enabled = false;
> -       pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
>  }
>
>  static void pqi_ofa_ctrl_unquiesce(struct pqi_ctrl_info *ctrl_info)
>  {
> -       pqi_ofa_free_host_buffer(ctrl_info);
> -       ctrl_info->pqi_mode_enabled = true;
> -       pqi_save_ctrl_mode(ctrl_info, PQI_MODE);
> -       ctrl_info->controller_online = true;
> -       pqi_ctrl_unblock_requests(ctrl_info);
>         pqi_start_heartbeat_timer(ctrl_info);
> -       pqi_schedule_update_time_worker(ctrl_info);
> -       pqi_clear_soft_reset_status(ctrl_info,
> -               PQI_SOFT_RESET_ABORT);
> -       pqi_scan_scsi_devices(ctrl_info);
> +       pqi_ctrl_unblock_requests(ctrl_info);
> +       pqi_ctrl_unblock_device_reset(ctrl_info);
> +       pqi_scsi_unblock_requests(ctrl_info);
> +       pqi_ctrl_unblock_scan(ctrl_info);
>  }
>
> -static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info,
> -       u32 total_size, u32 chunk_size)
> +static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info, u32
> total_size, u32 chunk_size)
>  {
> -       u32 sg_count;
> -       u32 size;
>         int i;
> -       struct pqi_sg_descriptor *mem_descriptor = NULL;
> +       u32 sg_count;
>         struct device *dev;
>         struct pqi_ofa_memory *ofap;
> -
> -       dev = &ctrl_info->pci_dev->dev;
> -
> -       sg_count = (total_size + chunk_size - 1);
> -       sg_count /= chunk_size;
> +       struct pqi_sg_descriptor *mem_descriptor;
> +       dma_addr_t dma_handle;
>
>         ofap = ctrl_info->pqi_ofa_mem_virt_addr;
>
> -       if (sg_count*chunk_size < total_size)
> +       sg_count = DIV_ROUND_UP(total_size, chunk_size);
> +       if (sg_count == 0 || sg_count > PQI_OFA_MAX_SG_DESCRIPTORS)
>                 goto out;
>
> -       ctrl_info->pqi_ofa_chunk_virt_addr =
> -                               kcalloc(sg_count, sizeof(void *),
> GFP_KERNEL);
> +       ctrl_info->pqi_ofa_chunk_virt_addr = kmalloc_array(sg_count,
> sizeof(void *), GFP_KERNEL);
>         if (!ctrl_info->pqi_ofa_chunk_virt_addr)
>                 goto out;
>
> -       for (size = 0, i = 0; size < total_size; size += chunk_size,
> i++) {
> -               dma_addr_t dma_handle;
> +       dev = &ctrl_info->pci_dev->dev;
>
> +       for (i = 0; i < sg_count; i++) {
>                 ctrl_info->pqi_ofa_chunk_virt_addr[i] =
> -                       dma_alloc_coherent(dev, chunk_size,
> &dma_handle,
> -                                          GFP_KERNEL);
> -
> +                       dma_alloc_coherent(dev, chunk_size,
> &dma_handle, GFP_KERNEL);
>                 if (!ctrl_info->pqi_ofa_chunk_virt_addr[i])
> -                       break;
> -
> +                       goto out_free_chunks;
>                 mem_descriptor = &ofap->sg_descriptor[i];
>                 put_unaligned_le64((u64)dma_handle, &mem_descriptor-
> >address);
>                 put_unaligned_le32(chunk_size, &mem_descriptor-
> >length);
>         }
>
> -       if (!size || size < total_size)
> -               goto out_free_chunks;
> -
>         put_unaligned_le32(CISS_SG_LAST, &mem_descriptor->flags);
>         put_unaligned_le16(sg_count, &ofap->num_memory_descriptors);
> -       put_unaligned_le32(size, &ofap->bytes_allocated);
> +       put_unaligned_le32(sg_count * chunk_size, &ofap-
> >bytes_allocated);
>
>         return 0;
>
> @@ -8416,82 +8190,87 @@ static int pqi_ofa_alloc_mem(struct
> pqi_ctrl_info *ctrl_info,
>         while (--i >= 0) {
>                 mem_descriptor = &ofap->sg_descriptor[i];
>                 dma_free_coherent(dev, chunk_size,
> -                               ctrl_info-
> >pqi_ofa_chunk_virt_addr[i],
> -                               get_unaligned_le64(&mem_descriptor-
> >address));
> +                       ctrl_info->pqi_ofa_chunk_virt_addr[i],
> +                       get_unaligned_le64(&mem_descriptor-
> >address));
>         }
>         kfree(ctrl_info->pqi_ofa_chunk_virt_addr);
>
>  out:
> -       put_unaligned_le32 (0, &ofap->bytes_allocated);
>         return -ENOMEM;
>  }
>
>  static int pqi_ofa_alloc_host_buffer(struct pqi_ctrl_info
> *ctrl_info)
>  {
>         u32 total_size;
> +       u32 chunk_size;
>         u32 min_chunk_size;
> -       u32 chunk_sz;
>
> -       total_size = le32_to_cpu(
> -                       ctrl_info->pqi_ofa_mem_virt_addr-
> >bytes_allocated);
> -       min_chunk_size = total_size / PQI_OFA_MAX_SG_DESCRIPTORS;
> +       if (ctrl_info->ofa_bytes_requested == 0)
> +               return 0;
>
> -       for (chunk_sz = total_size; chunk_sz >= min_chunk_size;
> chunk_sz /= 2)
> -               if (!pqi_ofa_alloc_mem(ctrl_info, total_size,
> chunk_sz))
> +       total_size = PAGE_ALIGN(ctrl_info->ofa_bytes_requested);
> +       min_chunk_size = DIV_ROUND_UP(total_size,
> PQI_OFA_MAX_SG_DESCRIPTORS);
> +       min_chunk_size = PAGE_ALIGN(min_chunk_size);
> +
> +       for (chunk_size = total_size; chunk_size >= min_chunk_size;)
> {
> +               if (pqi_ofa_alloc_mem(ctrl_info, total_size,
> chunk_size) == 0)
>                         return 0;
> +               chunk_size /= 2;
> +               chunk_size = PAGE_ALIGN(chunk_size);
> +       }
>
>         return -ENOMEM;
>  }
>
> -static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info
> *ctrl_info,
> -       u32 bytes_requested)
> +static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       struct pqi_ofa_memory *pqi_ofa_memory;
>         struct device *dev;
> +       struct pqi_ofa_memory *ofap;
>
>         dev = &ctrl_info->pci_dev->dev;
> -       pqi_ofa_memory = dma_alloc_coherent(dev,
> -
> PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
> -                                           &ctrl_info-
> >pqi_ofa_mem_dma_handle,
> -                                           GFP_KERNEL);
>
> -       if (!pqi_ofa_memory)
> +       ofap = dma_alloc_coherent(dev, sizeof(*ofap),
> +               &ctrl_info->pqi_ofa_mem_dma_handle, GFP_KERNEL);
> +       if (!ofap)
>                 return;
>
> -       put_unaligned_le16(PQI_OFA_VERSION, &pqi_ofa_memory-
> >version);
> -       memcpy(&pqi_ofa_memory->signature, PQI_OFA_SIGNATURE,
> -                                       sizeof(pqi_ofa_memory-
> >signature));
> -       pqi_ofa_memory->bytes_allocated =
> cpu_to_le32(bytes_requested);
> -
> -       ctrl_info->pqi_ofa_mem_virt_addr = pqi_ofa_memory;
> +       ctrl_info->pqi_ofa_mem_virt_addr = ofap;
>
>         if (pqi_ofa_alloc_host_buffer(ctrl_info) < 0) {
> -               dev_err(dev, "Failed to allocate host buffer of size
> = %u",
> -                       bytes_requested);
> +               dev_err(dev,
> +                       "failed to allocate host buffer for Online
> Firmware Activation\n");
> +               dma_free_coherent(dev, sizeof(*ofap), ofap,
> ctrl_info->pqi_ofa_mem_dma_handle);
> +               ctrl_info->pqi_ofa_mem_virt_addr = NULL;
> +               return;
>         }
>
> -       return;
> +       put_unaligned_le16(PQI_OFA_VERSION, &ofap->version);
> +       memcpy(&ofap->signature, PQI_OFA_SIGNATURE, sizeof(ofap-
> >signature));
>  }
>
>  static void pqi_ofa_free_host_buffer(struct pqi_ctrl_info
> *ctrl_info)
>  {
> -       int i;
> -       struct pqi_sg_descriptor *mem_descriptor;
> +       unsigned int i;
> +       struct device *dev;
>         struct pqi_ofa_memory *ofap;
> +       struct pqi_sg_descriptor *mem_descriptor;
> +       unsigned int num_memory_descriptors;
>
>         ofap = ctrl_info->pqi_ofa_mem_virt_addr;
> -
>         if (!ofap)
>                 return;
>
> -       if (!ofap->bytes_allocated)
> +       dev = &ctrl_info->pci_dev->dev;
> +
> +       if (get_unaligned_le32(&ofap->bytes_allocated) == 0)
>                 goto out;
>
>         mem_descriptor = ofap->sg_descriptor;
> +       num_memory_descriptors =
> +               get_unaligned_le16(&ofap->num_memory_descriptors);
>
> -       for (i = 0; i < get_unaligned_le16(&ofap-
> >num_memory_descriptors);
> -               i++) {
> -               dma_free_coherent(&ctrl_info->pci_dev->dev,
> +       for (i = 0; i < num_memory_descriptors; i++) {
> +               dma_free_coherent(dev,
>                         get_unaligned_le32(&mem_descriptor[i].length)
> ,
>                         ctrl_info->pqi_ofa_chunk_virt_addr[i],
>                         get_unaligned_le64(&mem_descriptor[i].address
> ));
> @@ -8499,47 +8278,46 @@ static void pqi_ofa_free_host_buffer(struct
> pqi_ctrl_info *ctrl_info)
>         kfree(ctrl_info->pqi_ofa_chunk_virt_addr);
>
>  out:
> -       dma_free_coherent(&ctrl_info->pci_dev->dev,
> -                       PQI_OFA_MEMORY_DESCRIPTOR_LENGTH, ofap,
> -                       ctrl_info->pqi_ofa_mem_dma_handle);
> +       dma_free_coherent(dev, sizeof(*ofap), ofap,
> +               ctrl_info->pqi_ofa_mem_dma_handle);
>         ctrl_info->pqi_ofa_mem_virt_addr = NULL;
>  }
>
>  static int pqi_ofa_host_memory_update(struct pqi_ctrl_info
> *ctrl_info)
>  {
> +       u32 buffer_length;
>         struct pqi_vendor_general_request request;
> -       size_t size;
>         struct pqi_ofa_memory *ofap;
>
>         memset(&request, 0, sizeof(request));
>
> -       ofap = ctrl_info->pqi_ofa_mem_virt_addr;
> -
>         request.header.iu_type = PQI_REQUEST_IU_VENDOR_GENERAL;
>         put_unaligned_le16(sizeof(request) -
> PQI_REQUEST_HEADER_LENGTH,
>                 &request.header.iu_length);
>         put_unaligned_le16(PQI_VENDOR_GENERAL_HOST_MEMORY_UPDATE,
>                 &request.function_code);
>
> +       ofap = ctrl_info->pqi_ofa_mem_virt_addr;
> +
>         if (ofap) {
> -               size = offsetof(struct pqi_ofa_memory, sg_descriptor)
> +
> +               buffer_length = offsetof(struct pqi_ofa_memory,
> sg_descriptor) +
>                         get_unaligned_le16(&ofap-
> >num_memory_descriptors) *
>                         sizeof(struct pqi_sg_descriptor);
>
>                 put_unaligned_le64((u64)ctrl_info-
> >pqi_ofa_mem_dma_handle,
>                         &request.data.ofa_memory_allocation.buffer_ad
> dress);
> -               put_unaligned_le32(size,
> +               put_unaligned_le32(buffer_length,
>                         &request.data.ofa_memory_allocation.buffer_le
> ngth);
> -
>         }
>
>         return pqi_submit_raid_request_synchronous(ctrl_info,
> &request.header,
> -               0, NULL, NO_TIMEOUT);
> +               0, NULL);
>  }
>
> -static int pqi_ofa_ctrl_restart(struct pqi_ctrl_info *ctrl_info)
> +static int pqi_ofa_ctrl_restart(struct pqi_ctrl_info *ctrl_info,
> unsigned int delay_secs)
>  {
> -       msleep(PQI_POST_RESET_DELAY_B4_MSGU_READY);
> +       ssleep(delay_secs);
> +
>         return pqi_ctrl_init_resume(ctrl_info);
>  }
>
> @@ -8597,7 +8375,6 @@ static void
> pqi_take_ctrl_offline_deferred(struct pqi_ctrl_info *ctrl_info)
>         pqi_cancel_update_time_worker(ctrl_info);
>         pqi_ctrl_wait_until_quiesced(ctrl_info);
>         pqi_fail_all_outstanding_requests(ctrl_info);
> -       pqi_clear_all_queued_raid_bypass_retries(ctrl_info);
>         pqi_ctrl_unblock_requests(ctrl_info);
>  }
>
> @@ -8730,24 +8507,12 @@ static void pqi_shutdown(struct pci_dev
> *pci_dev)
>                 return;
>         }
>
> -       pqi_disable_events(ctrl_info);
>         pqi_wait_until_ofa_finished(ctrl_info);
> -       pqi_cancel_update_time_worker(ctrl_info);
> -       pqi_cancel_rescan_worker(ctrl_info);
> -       pqi_cancel_event_worker(ctrl_info);
> -
> -       pqi_ctrl_shutdown_start(ctrl_info);
> -       pqi_ctrl_wait_until_quiesced(ctrl_info);
> -
> -       rc = pqi_ctrl_wait_for_pending_io(ctrl_info, NO_TIMEOUT);
> -       if (rc) {
> -               dev_err(&pci_dev->dev,
> -                       "wait for pending I/O failed\n");
> -               return;
> -       }
>
> +       pqi_scsi_block_requests(ctrl_info);
>         pqi_ctrl_block_device_reset(ctrl_info);
> -       pqi_wait_until_lun_reset_finished(ctrl_info);
> +       pqi_ctrl_block_requests(ctrl_info);
> +       pqi_ctrl_wait_until_quiesced(ctrl_info);
>
>         /*
>          * Write all data in the controller's battery-backed cache to
> @@ -8758,15 +8523,6 @@ static void pqi_shutdown(struct pci_dev
> *pci_dev)
>                 dev_err(&pci_dev->dev,
>                         "unable to flush controller cache\n");
>
> -       pqi_ctrl_block_requests(ctrl_info);
> -
> -       rc = pqi_ctrl_wait_for_pending_sync_cmds(ctrl_info);
> -       if (rc) {
> -               dev_err(&pci_dev->dev,
> -                       "wait for pending sync cmds failed\n");
> -               return;
> -       }
> -
>         pqi_crash_if_pending_command(ctrl_info);
>         pqi_reset(ctrl_info);
>  }
> @@ -8801,19 +8557,18 @@ static __maybe_unused int pqi_suspend(struct
> pci_dev *pci_dev, pm_message_t stat
>
>         ctrl_info = pci_get_drvdata(pci_dev);
>
> -       pqi_disable_events(ctrl_info);
> -       pqi_cancel_update_time_worker(ctrl_info);
> -       pqi_cancel_rescan_worker(ctrl_info);
> -       pqi_wait_until_scan_finished(ctrl_info);
> -       pqi_wait_until_lun_reset_finished(ctrl_info);
>         pqi_wait_until_ofa_finished(ctrl_info);
> -       pqi_flush_cache(ctrl_info, SUSPEND);
> +
> +       pqi_ctrl_block_scan(ctrl_info);
> +       pqi_scsi_block_requests(ctrl_info);
> +       pqi_ctrl_block_device_reset(ctrl_info);
>         pqi_ctrl_block_requests(ctrl_info);
>         pqi_ctrl_wait_until_quiesced(ctrl_info);
> -       pqi_wait_until_inbound_queues_empty(ctrl_info);
> -       pqi_ctrl_wait_for_pending_io(ctrl_info, NO_TIMEOUT);
> +       pqi_flush_cache(ctrl_info, SUSPEND);
>         pqi_stop_heartbeat_timer(ctrl_info);
>
> +       pqi_crash_if_pending_command(ctrl_info);
> +
>         if (state.event == PM_EVENT_FREEZE)
>                 return 0;
>
> @@ -8846,8 +8601,10 @@ static __maybe_unused int pqi_resume(struct
> pci_dev *pci_dev)
>                                 pci_dev->irq, rc);
>                         return rc;
>                 }
> -               pqi_start_heartbeat_timer(ctrl_info);
> +               pqi_ctrl_unblock_device_reset(ctrl_info);
>                 pqi_ctrl_unblock_requests(ctrl_info);
> +               pqi_scsi_unblock_requests(ctrl_info);
> +               pqi_ctrl_unblock_scan(ctrl_info);
>                 return 0;
>         }
>
> @@ -9288,7 +9045,7 @@ static void __attribute__((unused))
> verify_structures(void)
>         BUILD_BUG_ON(offsetof(struct pqi_iu_header,
>                 response_queue_id) != 0x4);
>         BUILD_BUG_ON(offsetof(struct pqi_iu_header,
> -               work_area) != 0x6);
> +               driver_flags) != 0x6);
>         BUILD_BUG_ON(sizeof(struct pqi_iu_header) != 0x8);
>
>         BUILD_BUG_ON(offsetof(struct pqi_aio_error_info,
> @@ -9386,7 +9143,7 @@ static void __attribute__((unused))
> verify_structures(void)
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
>                 header.iu_length) != 2);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
> -               header.work_area) != 6);
> +               header.driver_flags) != 6);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
>                 request_id) != 8);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
> @@ -9442,7 +9199,7 @@ static void __attribute__((unused))
> verify_structures(void)
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
>                 header.iu_length) != 2);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
> -               header.work_area) != 6);
> +               header.driver_flags) != 6);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
>                 request_id) != 8);
>         BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
> @@ -9466,7 +9223,7 @@ static void __attribute__((unused))
> verify_structures(void)
>         BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
>                 header.response_queue_id) != 4);
>         BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
> -               header.work_area) != 6);
> +               header.driver_flags) != 6);
>         BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
>                 request_id) != 8);
>         BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
> @@ -9495,7 +9252,7 @@ static void __attribute__((unused))
> verify_structures(void)
>         BUILD_BUG_ON(offsetof(struct pqi_aio_path_request,
>                 header.response_queue_id) != 4);
>         BUILD_BUG_ON(offsetof(struct pqi_aio_path_request,
> -               header.work_area) != 6);
> +               header.driver_flags) != 6);
>         BUILD_BUG_ON(offsetof(struct pqi_aio_path_request,
>                 request_id) != 8);
>         BUILD_BUG_ON(offsetof(struct pqi_aio_path_request,
>




  parent reply	other threads:[~2021-01-15 21:15 UTC|newest]

Thread overview: 91+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-10 20:34 [PATCH V3 00/25] smartpqi updates Don Brace
2020-12-10 20:34 ` [PATCH V3 01/25] smartpqi: add support for product id Don Brace
2021-01-07 16:43   ` Martin Wilck
2020-12-10 20:34 ` [PATCH V3 02/25] smartpqi: refactor aio submission code Don Brace
2021-01-07 16:43   ` Martin Wilck
2020-12-10 20:34 ` [PATCH V3 03/25] smartpqi: refactor build sg list code Don Brace
2021-01-07 16:43   ` Martin Wilck
2020-12-10 20:34 ` [PATCH V3 04/25] smartpqi: add support for raid5 and raid6 writes Don Brace
2021-01-07 16:44   ` Martin Wilck
2021-01-08 22:56     ` Don.Brace
2021-01-13 10:26       ` Martin Wilck
2020-12-10 20:34 ` [PATCH V3 05/25] smartpqi: add support for raid1 writes Don Brace
2021-01-07 16:44   ` Martin Wilck
2021-01-09 16:56     ` Don.Brace
2020-12-10 20:34 ` [PATCH V3 06/25] smartpqi: add support for BMIC sense feature cmd and feature bits Don Brace
2021-01-07 16:44   ` Martin Wilck
2021-01-11 17:22     ` Don.Brace
2021-01-22 16:45     ` Don.Brace
2021-01-22 19:04       ` Martin Wilck
2020-12-10 20:35 ` [PATCH V3 07/25] smartpqi: update AIO Sub Page 0x02 support Don Brace
2021-01-07 16:44   ` Martin Wilck
2021-01-11 20:53     ` Don.Brace
2020-12-10 20:35 ` [PATCH V3 08/25] smartpqi: add support for long firmware version Don Brace
2021-01-07 16:45   ` Martin Wilck
2021-01-11 22:25     ` Don.Brace
2021-01-22 20:01     ` Don.Brace
2020-12-10 20:35 ` [PATCH V3 09/25] smartpqi: align code with oob driver Don Brace
2021-01-08  0:13   ` Martin Wilck
2020-12-10 20:35 ` [PATCH V3 10/25] smartpqi: add stream detection Don Brace
2021-01-08  0:14   ` Martin Wilck
2021-01-15 21:58     ` Don.Brace
2020-12-10 20:35 ` [PATCH V3 11/25] smartpqi: add host level stream detection enable Don Brace
2021-01-08  0:13   ` Martin Wilck
2021-01-12 20:28     ` Don.Brace
2020-12-10 20:35 ` [PATCH V3 12/25] smartpqi: enable support for NVMe encryption Don Brace
2021-01-08  0:14   ` Martin Wilck
2020-12-10 20:35 ` [PATCH V3 13/25] smartpqi: disable write_same for nvme hba disks Don Brace
2021-01-08  0:13   ` Martin Wilck
2020-12-10 20:35 ` [PATCH V3 14/25] smartpqi: fix driver synchronization issues Don Brace
2021-01-07 23:32   ` Martin Wilck
2021-01-08  4:13     ` Martin K. Petersen
2021-01-15 21:13     ` Don.Brace [this message]
2021-01-27 23:01     ` Don.Brace
     [not found]       ` <c1e6b199f5ccda5ccec5223dfcbd1fba22171c86.camel@suse.com>
2021-02-01 22:47         ` Don.Brace
2020-12-10 20:35 ` [PATCH V3 15/25] smartpqi: fix host qdepth limit Don Brace
2020-12-14 17:54   ` Paul Menzel
2020-12-15 20:23     ` Don.Brace
2021-01-07 23:43       ` Martin Wilck
2021-01-15 21:17         ` Don.Brace
2021-01-19 10:33           ` John Garry
2021-01-19 14:12             ` Martin Wilck
2021-01-19 17:43               ` Paul Menzel
2021-01-20 16:42               ` Donald Buczek
2021-01-20 17:03                 ` Don.Brace
2021-01-20 18:35                 ` Martin Wilck
2021-02-10 15:27             ` Don.Brace
2021-02-10 15:42               ` John Garry
2021-02-10 16:29                 ` Don.Brace
2021-03-29 21:15                   ` Paul Menzel
2021-03-29 21:16                     ` Paul Menzel
2021-03-30 14:37                       ` Donald Buczek
2020-12-10 20:35 ` [PATCH V3 16/25] smartpqi: convert snprintf to scnprintf Don Brace
2021-01-07 23:51   ` Martin Wilck
2020-12-10 20:35 ` [PATCH V3 17/25] smartpqi: change timing of release of QRM memory during OFA Don Brace
2021-01-08  0:14   ` Martin Wilck
2021-01-27 17:46     ` Don.Brace
2020-12-10 20:36 ` [PATCH V3 18/25] smartpqi: return busy indication for IOCTLs when ofa is active Don Brace
2020-12-10 20:36 ` [PATCH V3 19/25] smartpqi: add phy id support for the physical drives Don Brace
2021-01-08  0:03   ` Martin Wilck
2020-12-10 20:36 ` [PATCH V3 20/25] smartpqi: update sas initiator_port_protocols and target_port_protocols Don Brace
2021-01-08  0:12   ` Martin Wilck
2020-12-10 20:36 ` [PATCH V3 21/25] smartpqi: add additional logging for LUN resets Don Brace
2021-01-08  0:27   ` Martin Wilck
2021-01-25 17:09     ` Don.Brace
2020-12-10 20:36 ` [PATCH V3 22/25] smartpqi: update enclosure identifier in sysf Don Brace
2021-01-08  0:30   ` Martin Wilck
2021-01-25 17:13     ` Don.Brace
2021-01-25 19:44       ` Martin Wilck
2021-01-25 20:36         ` Don.Brace
2020-12-10 20:36 ` [PATCH V3 23/25] smartpqi: correct system hangs when resuming from hibernation Don Brace
2021-01-08  0:34   ` Martin Wilck
2021-01-27 17:39     ` Don.Brace
2021-01-27 17:45       ` Martin Wilck
2020-12-10 20:36 ` [PATCH V3 24/25] smartpqi: add new pci ids Don Brace
2021-01-08  0:35   ` Martin Wilck
2020-12-10 20:36 ` [PATCH V3 25/25] smartpqi: update version to 2.1.6-005 Don Brace
2020-12-21 14:31 ` [PATCH V3 00/25] smartpqi updates Donald Buczek
     [not found]   ` <SN6PR11MB2848D8C9DF9856A2B7AA69ACE1C00@SN6PR11MB2848.namprd11.prod.outlook.com>
2020-12-22 13:13     ` Donald Buczek
2020-12-28 15:57       ` Don.Brace
2020-12-28 19:25         ` Don.Brace
2020-12-28 22:36           ` Donald Buczek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=SN6PR11MB28487F1C94939FC4B096E0CFE1A70@SN6PR11MB2848.namprd11.prod.outlook.com \
    --to=don.brace@microchip.com \
    --cc=Gerry.Morong@microchip.com \
    --cc=Justin.Lindley@microchip.com \
    --cc=Kevin.Barnett@microchip.com \
    --cc=Mahesh.Rajashekhara@microchip.com \
    --cc=POSWALD@suse.com \
    --cc=Scott.Benesh@microchip.com \
    --cc=Scott.Teel@microchip.com \
    --cc=hch@infradead.org \
    --cc=jejb@linux.vnet.ibm.com \
    --cc=joseph.szczypek@hpe.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=mwilck@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.