[GIT] isci: fixes and cleanups

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The isci git tree:

	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git master

...has been updated with the following:

1/ task lifetime fixes
2/ removal of drivers/scsi/isci/deprecated.c (os abstraction layer)
3/ dma api and kmap fixes
4/ locking cleanups (host_quiesce_lock and remote_device_lock removed)
5/ first round of lldd_dev lifetime fixes
6/ workaround for a port task scheduler silicon issue
7/ various other fixes and cleanups
8/ userspace visible changes
   - sysfs 'isci_id' attribute under hostX to identify the controller
   - phy enable/disable support

Diffstat, log, and and the lldd portion of the diff included below (i.e.
git diff 3077cf00.. $(gls drivers/scsi/isci/ | grep -v /core/)).  I
could post these as separate patches but I thought I would conserve list
bandwidth for the upcoming posting of the core as a set of omnibus
patches. 

Dan Williams (14):
      isci: fix sas address reporting
      isci: rework timer api
      isci: fix hang after target reset
      isci: pad stp and smp request sizes
      isci: enable isci for dmar builds
      isci: kill isci_host list in favor of an array
      isci: remove sci_device_handle
      isci: kill "host quiesce" mechanism
      isci: replace isci_remote_device completion with event queue
      isci: preallocate remote devices
      isci: replace remote_device_lock  with scic_lock
      isci: cleanup debug leftovers in isci.h
      isci: Errors in the submit path for SATA devices manage the ap lock.
      isci: add "isci_id" attribute

Dave Jiang (7):
      isci: Removed special macros that does 64bit address math
      isci: Make the driver copy data directly from and to sg for PIO
      isci: have the driver use native SG calls and DMA-API
      isci: Change event notify calls from scic_cb_* to isci_event_*
      isci: Removing deprecated functions
      isci: Adding support for phy enable and disable
      isci: Cleanup warning messages for phy resets

Jeff Skirvin (12):
      isci: isci_request_cleanup_completed_loiterer checks task before task_done
      isci: Changes in isci_host_completion_routine
      isci: fix completion / abort path.
      isci: Any reset indicated on an I/O completion escalates it to the error path.
      isci: save the i/o tag outside the scic request structure.
      isci: Cleaning up task execute path.
      isci: Code review change for completion pointer cleanup.
      isci: Termination handling cleanup, added termination timeouts.
      isci: Fix TMF build for SAS/SATA LUN reset cases.
      isci: Fixed BUG_ON in isci_abort_task_process_cb callback.
      isci: Always set response/status for requests going into the error path.
      isci: All pending requests are terminated before stopping the device.

Pawel Marek (1):
      isci: controller stop/start fixes

Piotr Sawicki (1):
      isci: handle cases where a d2h fis is used report an ncq error

Tomasz Chudy (1):
      isci: workaround port task scheduler starvation issue

 drivers/scsi/Kconfig                               |    3 -
 drivers/scsi/isci/Makefile                         |    2 +-
 drivers/scsi/isci/core/sci_util.c                  |   31 +
 drivers/scsi/isci/core/sci_util.h                  |   51 +--
 drivers/scsi/isci/core/scic_port.h                 |   17 -
 drivers/scsi/isci/core/scic_sds_controller.c       |  215 ++++--
 drivers/scsi/isci/core/scic_sds_controller.h       |   29 +-
 drivers/scsi/isci/core/scic_sds_phy.c              |  166 +++--
 drivers/scsi/isci/core/scic_sds_phy.h              |    3 +
 drivers/scsi/isci/core/scic_sds_port.c             |  399 ++++++++---
 drivers/scsi/isci/core/scic_sds_port.h             |    9 +
 .../isci/core/scic_sds_port_configuration_agent.c  |   10 +-
 drivers/scsi/isci/core/scic_sds_remote_device.c    |   21 +-
 drivers/scsi/isci/core/scic_sds_request.c          |  324 +++++----
 drivers/scsi/isci/core/scic_sds_request.h          |   39 +-
 .../scsi/isci/core/scic_sds_smp_remote_device.c    |    5 +-
 drivers/scsi/isci/core/scic_sds_smp_request.c      |  124 ++--
 .../scsi/isci/core/scic_sds_stp_packet_request.c   |   20 +-
 .../scsi/isci/core/scic_sds_stp_remote_device.c    |  135 ++--
 drivers/scsi/isci/core/scic_sds_stp_request.c      |  284 +++-----
 drivers/scsi/isci/core/scic_sds_stp_request.h      |    2 +-
 .../isci/core/scic_sds_unsolicited_frame_control.c |   74 +-
 drivers/scsi/isci/core/scic_user_callback.h        |  736 ------------------
 drivers/scsi/isci/deprecated.c                     |  485 ------------
 drivers/scsi/isci/events.c                         |  163 ++---
 drivers/scsi/isci/events.h                         |  373 ++++++++++
 drivers/scsi/isci/host.c                           |  126 ++--
 drivers/scsi/isci/host.h                           |   36 +-
 drivers/scsi/isci/init.c                           |   84 +--
 drivers/scsi/isci/isci.h                           |   31 +-
 drivers/scsi/isci/phy.c                            |   91 ++--
 drivers/scsi/isci/port.c                           |   18 +-
 drivers/scsi/isci/port.h                           |    2 -
 drivers/scsi/isci/remote_device.c                  |  219 ++----
 drivers/scsi/isci/remote_device.h                  |   41 +-
 drivers/scsi/isci/request.c                        |  114 ++--
 drivers/scsi/isci/request.h                        |    3 +-
 drivers/scsi/isci/sata.c                           |    4 +-
 drivers/scsi/isci/task.c                           |  782 +++++++++++---------
 drivers/scsi/isci/task.h                           |  118 ++--
 drivers/scsi/isci/timers.c                         |  173 ++---
 drivers/scsi/isci/timers.h                         |   60 +--
 42 files changed, 2484 insertions(+), 3138 deletions(-)
 delete mode 100644 drivers/scsi/isci/core/scic_user_callback.h
 delete mode 100644 drivers/scsi/isci/deprecated.c
 create mode 100644 drivers/scsi/isci/events.h

commit 119c8f35648d7cbc24339eeb9d02c7c2e35db685
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Thu Mar 10 00:01:43 2011 -0800

    isci: add "isci_id" attribute
    
    Allow each controller to be identified via sysfs.
    
    # cat /sys/class/scsi_host/host13/isci_id
    1
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit fa4d37357b355fde9c9fc8ec3c3eef932d16c10c
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Tue Mar 8 20:32:16 2011 -0700

    isci: All pending requests are terminated before stopping the device.
    
    Make sure all pending I/O including any in the libsas error handler
    process is cleaned-up.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 828339b14f3948c6fa023353d1dfa5f67e549542
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Mon Mar 7 16:40:47 2011 -0700

    isci: Always set response/status for requests going into the error path.
    
    In the case of I/O requests being failed because of a required device
    reset condition, set the response and status to indicate an I/O failure.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit ec745eb31b7e12791bd74988e90aea02242e98f0
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Wed Mar 9 21:27:46 2011 -0800

    isci: Errors in the submit path for SATA devices manage the ap lock.
    
    Since libsas takes the domain device sata_dev.ap->lock before submitting
    a task, error completions in the submit path for SATA devices must
    unlock/relock when completing the sas_task back to libsas.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 7df663b34aeb46cd310873ab3f3a7e5a031e4ed0
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:58 2011 -0800

    isci: Fixed BUG_ON in isci_abort_task_process_cb callback.
    
    The request may be in the "aborted" or the "completed" state when
    performing a task management operation on it.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 0b08e9fe99941263e3757dd8abf8adf43977470f
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:56 2011 -0800

    isci: Fix TMF build for SAS/SATA LUN reset cases.
    
    In the case where a SAS or SATA LUN reset TMF is built a NULL pointer
    dereference occurred because of the (unused) callback data pointer.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>

commit cc476493a6883df996c5d5912e677795fcb9b65b
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:52 2011 -0800

    isci: Termination handling cleanup, added termination timeouts.
    
    Added a request "dead" state for use when a termination wait times-out.
    
    isci_terminate_pending_requests now detaches the device's pending list
    and terminates each entry on the detached list.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit afdfc7a2f730f7b21f36507e2d8389d4b82c3b13
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:50 2011 -0800

    isci: Code review change for completion pointer cleanup.
    
    Since the request structure contains a pointer to the completion to be
    used if the request is being aborted or terminated, there is no reason
    to pass the completion as a pointer to isci_terminate_request_core().
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit a2f5738193192f6dda498f448ff6bb1c44662816
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Tue Mar 8 19:22:07 2011 -0700

    isci: Cleaning up task execute path.
    
    Made sure the device ready check accounts for all states.
    Moved the aborted task check into the loop of pulling task requests
    off of the submitted list.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    [remove host and device starting state checks]
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 871cd89bc64acb03fb202c3849d1b5378b637b06
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:46 2011 -0800

    isci: save the i/o tag outside the scic request structure.
    
    The pointer to the core representation of a request is marked NULL at
    completion, but we need to save the i/o tag for task management.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    [revise changelog]
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 03674d66d44ed96b4ab4b96209ab1a8a3ab174e3
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:44 2011 -0800

    isci: Any reset indicated on an I/O completion escalates it to the error path.
    
    If there is a pending device reset, the I/O is used to accomplish the reset by setting the
    RESET bit in the task status, and then putting the task into the error handler
    path using sas abort task.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit faa7690e2ba061a79ef8d3fdaf63976d455e1cf4
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:42 2011 -0800

    isci: fix completion / abort path.
    
    Corrected use of the request state_lock in the completion callback.
    
    In the case where an abort (or reset) thread is trying to terminate an
    I/O request, it sets the request state to "aborting" (or "terminating")
    if the state is still "starting".  One of the bugs was to never set the
    state to "completed".  Another was to not correctly recognize the
    situation where the I/O had completed but the sas_task was still pending
    callback to task_done - this was typically a problem in the LUN and
    device reset cases.
    
    It is now possible that we leave isci_task_abort_task() with
    request->io_request_completion pointing to localy allocated
    aborted_io_completion struct. It may result in a system crash.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Maciej Trela <Maciej.Trela@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit c49bd907f09e753dafc23fad95bffbd70dfa7e8c
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:40 2011 -0800

    isci: Changes in isci_host_completion_routine
    
    Changes to move management of the reqs_in_process entry for the request here.
    Made changes to note when the task is already in the abort path and
    cannot be completed through callbacks.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 563ee3a3878bf066495a22e1ef07e71032c8181b
Author: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
Date:   Fri Mar 4 14:06:38 2011 -0800

    isci: isci_request_cleanup_completed_loiterer checks task before task_done
    
    In the condition where outstanding I/Os are being cleaned from the device
    requests in process list, the cleanup function needs to check that the
    request is actually a sas-task and not a task management function.
    
    Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit c89d0a12ddd42c7d3e26fe84317e99320885d5a3
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Tue Mar 8 21:30:28 2011 -0800

    isci: cleanup debug leftovers in isci.h
    
    Reported-by: James Bottomley <James.Bottomley@xxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit bbca7739a6b4dbb8fb0452fa7953f03a4fcd9b26
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Thu Mar 3 18:01:43 2011 -0800

    isci: replace remote_device_lock  with scic_lock
    
    The remote_device_lock is currently used to protect a controller global
    resource (RNCs), but the remote_device_lock is per-port.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 8897a1f8f81685404521c2595542e0439f117da7
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Thu Mar 3 17:59:32 2011 -0800

    isci: preallocate remote devices
    
    Until we synchronize against device removal this limits the damage of
    use after free bugs to the driver's own objects.  Unless we implement
    reference counting we need to ensure at least a subset of a remote
    device is valid at all times.  We follow the lead of other libsas
    drivers that also preallocate devices.
    
    This also enforces maximum remote device accounting at the lldd layer,
    but the core may still run out of RNC's before we hit this limit.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit a713b1bb72faef44e803ec57b331e71bc90346f0
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Fri Mar 4 12:10:29 2011 -0800

    isci: replace isci_remote_device completion with event queue
    
    Replace the device completion infrastructure with the controller wide
    event queue.  There was a potential for the stop and ready notifications
    to corrupt each other, now that cannot happen.
    
    The stop pending flag cannot be used until devices are statically
    allocated.  We temporarily need to maintain a completion to handle
    waiting for an object that has disappeared, but we can at least stop
    scribbling on freed memory.
    
    A future change will also get rid of the "stopping" state as it should
    not be exposed to the rest of the driver.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit bb86966f2ce1773be8660a0b93fbeff9514b1229
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Mon Mar 7 14:47:35 2011 -0800

    isci: kill "host quiesce" mechanism
    
    The midlayer is already throttling i/o in the places where host_quiesce
    was trying to prevent further i/o to the device.  It's also problematic
    in that it holds a lock over GFP_KERNEL allocations.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit f8d8ced6e8d0b0903877ff3d1e412da1836c76c8
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Fri Mar 4 11:51:43 2011 -0800

    isci: remove sci_device_handle
    
    It belies the fact that isci_remote_device and scic_sds_remote_device
    are one in same object with the same lifetime rules.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit f7da6e00938a482298ec089816c7b52fee9d4ba8
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Mon Mar 7 16:02:25 2011 -0800

    isci: kill isci_host list in favor of an array
    
    isci_host_by_id() should have been a clue that an array would have been
    a simpler approach.
    
    Reported-by: James Bottomley <James.Bottomley@xxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 4c68db90e2301b4d672b9571aad6f47bc61e5a80
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Thu Mar 3 17:59:25 2011 -0800

    isci: enable isci for dmar builds
    
    Now that phys_to_virt() and virt_to_phys() have been removed we are no
    longer violating the dma mapping (or kmap apis).
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 0113f67b3f070712aa544f4c9a3668a106998121
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Thu Mar 3 14:58:11 2011 -0800

    isci: pad stp and smp request sizes
    
    Ross says:
     "The memory allocation for these requests doesnât take into account the
      additional memory needed when the code in
      scic_sds_s[mst]p_request_assign_buffers() shifts the struct
      scu_task_context so that it is cache line aligned:
    
      In an example from my machine, total buffer that Iâve given to SCIC goes
      from 0x410024566f84 to 0x410024567308.  From this same example, this
      call shifts my task_context_buffer from 0x410024567208 to
      0x410024567240.
    
      This means that the task_context_buffer that used to range from
      0x410024567208 to 0x410024567308 instead now goes from 0x410024567240 to
      0x410024567340.
    
      When the memset() call at the end of scic_task_request_construct()
      clears out this task_context_buffer, it does so from 0x410024567240 to
      0x410024567340, effectively killing whatever buffer follows this
      allocation in memory."
    
    djbw:
    Use the kernel's PTR_ALIGN instead of
    scic_sds_request_align_task_context_buffer() and SMP_CACHE_BYTES instead of
    the local CACHE_LINE_SIZE definition.
    
    TODO: These allocations really want to be better defined in a union rather
    than opaque buffers carved up by macros.
    
    Reported-by: Ross Zwisler <ross.zwisler@xxxxxxxxx>
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 72bea0ed7761942d5b09b38c0b149e4fc41f2807
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Wed Mar 2 16:45:18 2011 -0800

    isci: fix hang after target reset
    
    When aborting a task context we need to be sure that the hardware has acted on
    this request (retrieved the task context) before invalidating the remote node
    context.  In the case of the "dummy" task context and remote node we do not
    have the full state machine that goes through the complete tc abort and rnc
    invalidate states.  Instead we ensure the hardware has seen and acted on
    
    Signed-off-by: Jacek Danecki <Jacek.Danecki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 1cca16b180063d36a96ac21a5dc60736983151b3
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Mar 2 13:10:45 2011 -0800

    isci: Cleanup warning messages for phy resets
    
    Moving some of the chattiness of warning messages to debug so only the Linux
    system messages are shown.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 3da551128b49035dfcaa43c1bbba82e147d18b32
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Mar 2 12:31:24 2011 -0800

    isci: Adding support for phy enable and disable
    
    Adding support for PHY_FUNC_LINK_RESET and PHY_FUNC_DISABLE. This allow the
    sysfs knob enable (both 0 and 1) and link_reset to work properly.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit e10094cbc7245fafdcc9d03f909a1a5eab6b1829
Author: Pawel Marek <pawel.marek@xxxxxxxxx>
Date:   Tue Mar 1 12:31:06 2011 -0800

    isci: controller stop/start fixes
    
    Core reworks to support stopping and re-starting the controller, lays the
    groundwork for phy disable / re-enable and fixes other bugs around port/phy
    setup/teardown.
    
    Signed-off-by: Pawel Marek <pawel.marek@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 0a1292e1268b000215e504e5beae3501fc01ac97
Author: Piotr Sawicki <piotr.sawicki@xxxxxxxxx>
Date:   Fri Feb 25 13:07:38 2011 -0800

    isci: handle cases where a d2h fis is used report an ncq error
    
    Observed that some devices return a d2h fis, treat like an sdb error fis.
    
    Signed-off-by: Piotr Sawicki <piotr.sawicki@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit c40a3a21e3fea3bcb29b903608361e172fa6e7d9
Author: Tomasz Chudy <Tomasz.Chudy@xxxxxxxxx>
Date:   Fri Feb 25 02:25:09 2011 -0800

    isci: workaround port task scheduler starvation issue
    
    There is a condition whereby TCs (task contexts) can jump to the head of
    the round robin queue causing indefinite starvation of pending tasks.
    Posting a TC to a suspended RNC (remote node context) causes the
    hardware to select that task first, but since the RNC is suspended the
    scheduler proceeds to the next task in the expected round robin fashion,
    restoring TC arbitration fairness.
    
    Signed-off-by: Tomasz Chudy <tomasz.chudy@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 8d32e5b2aefe0d5e966cc7f5c5e887aa2d2b6090
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Wed Mar 2 11:49:26 2011 -0800

    isci: rework timer api
    
    Prepare the timer api for the arrival of dynamic creation and
    destruction events from the core.  It pretended to do this previously
    but the core to date only used it in a static init-time only fashion.
    This is an interim fix until a cleaner event queue can be developed.
    
    1/ make all locking external to the api (add WARN_ONCE to verify)
    2/ add a timer_destroy interface (to be used by the core)
    3/ use del_timer_sync() prior to deallocating timer data
    4/ delete the "timer_list" indirection, we only have timers allocated
       for the isci_host
    5/ fix detection of timer list allocation errors
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit db3dd417bed5b2be0c95ace9e4b8871102ca5dcf
Author: Dan Williams <dan.j.williams@xxxxxxxxx>
Date:   Fri Feb 25 10:25:21 2011 -0800

    isci: fix sas address reporting
    
    Undo the open coded and incorrect translation of the oem parameter sas
    address to its libsas expected format.
    
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit 709637fec5ad729f864bebebcea378f725a1eea9
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Feb 23 15:57:33 2011 -0800

    isci: Removing deprecated functions
    
    Removed all callbacks in the deprecated.c. Core will call the appropriate
    functions directly.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit f8cd82b1be3aa8cf98c0e1da31d209829c54560f
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Feb 23 15:57:30 2011 -0800

    isci: Change event notify calls from scic_cb_* to isci_event_*
    
    Renaming the callbacks to apparopriate event notify calls for the LLDD.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit c32acaf4b9003f9d2d4855fdcc4e24c6a6836237
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Feb 23 15:57:27 2011 -0800

    isci: have the driver use native SG calls and DMA-API
    
    Remove abstraction for SG building and get rid of callbacks for getting
    DMA memory mapping.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit f67153dc4f1f6921cfb25c0e12b962f180a12756
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Wed Feb 23 15:57:24 2011 -0800

    isci: Make the driver copy data directly from and to sg for PIO
    
    We can copy the data directly to and from sg for SATA PIO read operations.
    There is no reason to involve the hardware SGL. In the process we also need
    to kmap the sg because we don't know where that can come from.
    
    We also do to not call phys_to_virt(). The driver already has the information.
    We can just calculcate the appropriate offets.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

commit c249d29aebcc4adda8d5d6e25a90aceaf0bbb501
Author: Dave Jiang <dave.jiang@xxxxxxxxx>
Date:   Tue Feb 22 16:39:32 2011 -0700

    isci: Removed special macros that does 64bit address math
    
    These macros are not necessary. We can do 64bit math directly.
    
    Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
    Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>


diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile
index 34f7af3..d402d67 100644
--- a/drivers/scsi/isci/Makefile
+++ b/drivers/scsi/isci/Makefile
@@ -8,7 +8,7 @@ EXTRA_CFLAGS += -DDISABLE_ATAPI
 EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/
 obj-$(CONFIG_SCSI_ISCI) += isci.o
 isci-objs := init.o phy.o request.o sata.o \
-	     remote_device.o port.o timers.o deprecated.o \
+	     remote_device.o port.o timers.o \
 	     host.o task.o events.o \
 	     core/scic_sds_controller.o  \
 	     core/scic_sds_remote_device.o    \
diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c
index 6911ea5..9d58e45 100644
--- a/drivers/scsi/isci/events.c
+++ b/drivers/scsi/isci/events.c
@@ -64,9 +64,10 @@
 #include "request.h"
 #include "sata.h"
 #include "task.h"
+#include "events.h"
 
 /**
- * scic_cb_timer_create() - This callback method asks the user to create a
+ * isci_event_timer_create() - This callback method asks the user to create a
  *    timer and provide a handle for this timer for use in further timer
  *    interactions. The appropriate isci timer object function is called to
  *    create a timer object.
@@ -74,40 +75,28 @@
  *    whenever the timer expires.
  * @controller: This parameter specifies the controller with which this timer
  *    is to be associated.
- * @cookie: This parameter specifies a piece of information that the user must
- *    retain.  This cookie is to be supplied by the user anytime a timeout
- *    occurs for the created timer.
+ * @cb_param: opaque callback parameter
  *
  * This method returns a handle to a timer object created by the user.  The
  * handle will be utilized for all further interactions relating to this timer.
  */
-void *scic_cb_timer_create(
-	struct scic_sds_controller *controller,
-	void (*timer_callback)(void *),
-	void *cookie)
+void *isci_event_timer_create(struct scic_sds_controller *scic,
+			      void (*timer_callback)(void *),
+			      void *cb_param)
 {
-	struct isci_host *isci_host;
-	struct isci_timer *timer = NULL;
-
-	isci_host = (struct isci_host *)sci_object_get_association(controller);
-
-	dev_dbg(&isci_host->pdev->dev,
-		"%s: isci_host = %p",
-		__func__, isci_host);
+	struct isci_host *ihost = sci_object_get_association(scic);
+	struct isci_timer *itimer;
 
-	timer = isci_timer_create(&isci_host->timer_list_struct,
-				  isci_host,
-				  cookie,
-				  timer_callback);
+	itimer = isci_timer_create(ihost, cb_param, timer_callback);
 
-	dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer);
+	dev_dbg(&ihost->pdev->dev, "%s: timer = %p\n", __func__, itimer);
 
-	return (void *)timer;
+	return itimer;
 }
 
 
 /**
- * scic_cb_timer_start() - This callback method asks the user to start the
+ * isci_event_timer_start() - This callback method asks the user to start the
  *    supplied timer. The appropriate isci timer object function is called to
  *    start the timer.
  * @controller: This parameter specifies the controller with which this timer
@@ -118,7 +107,7 @@ void *scic_cb_timer_create(
  *    where necessary.
  *
  */
-void scic_cb_timer_start(
+void isci_event_timer_start(
 	struct scic_sds_controller *controller,
 	void *timer,
 	u32 milliseconds)
@@ -137,7 +126,7 @@ void scic_cb_timer_start(
 }
 
 /**
- * scic_cb_timer_stop() - This callback method asks the user to stop the
+ * isci_event_timer_stop() - This callback method asks the user to stop the
  *    supplied timer. The appropriate isci timer object function is called to
  *    stop the timer.
  * @controller: This parameter specifies the controller with which this timer
@@ -145,14 +134,9 @@ void scic_cb_timer_start(
  * @timer: This parameter specifies the timer to be stopped.
  *
  */
-void scic_cb_timer_stop(
-	struct scic_sds_controller *controller,
-	void *timer)
+void isci_event_timer_stop(struct scic_sds_controller *controller, void *timer)
 {
-	struct isci_host *isci_host;
-
-	isci_host =
-		(struct isci_host *)sci_object_get_association(controller);
+	struct isci_host *isci_host = sci_object_get_association(controller);
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: isci_host = %p, timer = %p\n",
@@ -161,8 +145,18 @@ void scic_cb_timer_stop(
 	isci_timer_stop((struct isci_timer *)timer);
 }
 
+void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer)
+{
+        struct isci_host *ihost = sci_object_get_association(scic);
+
+	dev_dbg(&ihost->pdev->dev, "%s: ihost = %p, timer = %p\n",
+			__func__, ihost, timer);
+
+	isci_del_timer(ihost, timer);
+}
+
 /**
- * scic_cb_controller_start_complete() - This user callback will inform the
+ * isci_event_controller_start_complete() - This user callback will inform the
  *    user that the controller has finished the start process. The associated
  *    isci host adapter's start_complete function is called.
  * @controller: This parameter specifies the controller that was started.
@@ -170,7 +164,7 @@ void scic_cb_timer_stop(
  *    operation.  SCI_SUCCESS indicates successful completion.
  *
  */
-void scic_cb_controller_start_complete(
+void isci_event_controller_start_complete(
 	struct scic_sds_controller *controller,
 	enum sci_status completion_status)
 {
@@ -184,7 +178,7 @@ void scic_cb_controller_start_complete(
 }
 
 /**
- * scic_cb_controller_stop_complete() - This user callback will inform the user
+ * isci_event_controller_stop_complete() - This user callback will inform the user
  *    that the controller has finished the stop process. The associated isci
  *    host adapter's start_complete function is called.
  * @controller: This parameter specifies the controller that was stopped.
@@ -192,7 +186,7 @@ void scic_cb_controller_start_complete(
  *    operation.  SCI_SUCCESS indicates successful completion.
  *
  */
-void scic_cb_controller_stop_complete(
+void isci_event_controller_stop_complete(
 	struct scic_sds_controller *controller,
 	enum sci_status completion_status)
 {
@@ -205,7 +199,7 @@ void scic_cb_controller_stop_complete(
 }
 
 /**
- * scic_cb_io_request_complete() - This user callback will inform the user that
+ * isci_event_io_request_complete() - This user callback will inform the user that
  *    an IO request has completed.
  * @controller: This parameter specifies the controller on which the IO is
  *    completing.
@@ -216,7 +210,7 @@ void scic_cb_controller_stop_complete(
  *    operation.  SCI_SUCCESS indicates successful completion.
  *
  */
-void scic_cb_io_request_complete(
+void isci_event_io_request_complete(
 	struct scic_sds_controller *controller,
 	struct scic_sds_remote_device *remote_device,
 	struct scic_sds_request *scic_io_request,
@@ -239,7 +233,7 @@ void scic_cb_io_request_complete(
 }
 
 /**
- * scic_cb_task_request_complete() - This user callback will inform the user
+ * isci_event_task_request_complete() - This user callback will inform the user
  *    that a task management request completed.
  * @controller: This parameter specifies the controller on which the task
  *    management request is completing.
@@ -251,7 +245,7 @@ void scic_cb_io_request_complete(
  *    operation.  SCI_SUCCESS indicates successful completion.
  *
  */
-void scic_cb_task_request_complete(
+void isci_event_task_request_complete(
 	struct scic_sds_controller *controller,
 	struct scic_sds_remote_device *remote_device,
 	struct scic_sds_request *scic_task_request,
@@ -271,7 +265,7 @@ void scic_cb_task_request_complete(
 }
 
 /**
- * scic_cb_port_stop_complete() - This method informs the user when a stop
+ * isci_event_port_stop_complete() - This method informs the user when a stop
  *    operation on the port has completed.
  * @controller: This parameter represents the controller which contains the
  *    port.
@@ -281,17 +275,20 @@ void scic_cb_task_request_complete(
  *    being completed.
  *
  */
-void scic_cb_port_stop_complete(
+void isci_event_port_stop_complete(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	enum sci_status completion_status)
 {
-	pr_warn("%s:************************************************\n",
-		__func__);
+	struct isci_host *isci_host;
+
+	isci_host = (struct isci_host *)sci_object_get_association(controller);
+
+	dev_notice(&isci_host->pdev->dev, "Port stop complete\n");
 }
 
 /**
- * scic_cb_port_hard_reset_complete() - This method informs the user when a
+ * isci_event_port_hard_reset_complete() - This method informs the user when a
  *    hard reset on the port has completed.  This hard reset could have been
  *    initiated by the user or by the remote port.
  * @controller: This parameter represents the controller which contains the
@@ -302,7 +299,7 @@ void scic_cb_port_stop_complete(
  *    being completed.
  *
  */
-void scic_cb_port_hard_reset_complete(
+void isci_event_port_hard_reset_complete(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	enum sci_status completion_status)
@@ -314,7 +311,7 @@ void scic_cb_port_hard_reset_complete(
 }
 
 /**
- * scic_cb_port_ready() - This method informs the user that the port is now in
+ * isci_event_port_ready() - This method informs the user that the port is now in
  *    a ready state and can be utilized to issue IOs.
  * @controller: This parameter represents the controller which contains the
  *    port.
@@ -322,7 +319,7 @@ void scic_cb_port_hard_reset_complete(
  *    is being invoked.
  *
  */
-void scic_cb_port_ready(
+void isci_event_port_ready(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port)
 {
@@ -342,7 +339,7 @@ void scic_cb_port_ready(
 }
 
 /**
- * scic_cb_port_not_ready() - This method informs the user that the port is now
+ * isci_event_port_not_ready() - This method informs the user that the port is now
  *    not in a ready (i.e. busy) state and can't be utilized to issue IOs.
  * @controller: This parameter represents the controller which contains the
  *    port.
@@ -350,7 +347,7 @@ void scic_cb_port_ready(
  *    is being invoked.
  *
  */
-void scic_cb_port_not_ready(
+void isci_event_port_not_ready(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	u32 reason_code)
@@ -371,7 +368,7 @@ void scic_cb_port_not_ready(
 }
 
 /**
- * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that
+ * isci_event_port_invalid_link_up() - This method informs the SCI Core user that
  *    a phy/link became ready, but the phy is not allowed in the port.  In some
  *    situations the underlying hardware only allows for certain phy to port
  *    mappings.  If these mappings are violated, then this API is invoked.
@@ -383,17 +380,19 @@ void scic_cb_port_not_ready(
  *    a valid member of the port.
  *
  */
-void scic_cb_port_invalid_link_up(
+void isci_event_port_invalid_link_up(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	struct scic_sds_phy *phy)
 {
-	pr_warn("%s:************************************************\n",
-		__func__);
+	struct isci_host *isci_host;
+
+	isci_host = (struct isci_host *)sci_object_get_association(controller);
+	dev_warn(&isci_host->pdev->dev, "Invalid link up!\n");
 }
 
 /**
- * scic_cb_port_bc_change_primitive_received() - This callback method informs
+ * isci_event_port_bc_change_primitive_received() - This callback method informs
  *    the user that a broadcast change primitive was received.
  * @controller: This parameter represents the controller which contains the
  *    port.
@@ -403,7 +402,7 @@ void scic_cb_port_invalid_link_up(
  * @phy: This parameter specifies the phy on which the primitive was received.
  *
  */
-void scic_cb_port_bc_change_primitive_received(
+void isci_event_port_bc_change_primitive_received(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	struct scic_sds_phy *phy)
@@ -422,7 +421,7 @@ void scic_cb_port_bc_change_primitive_received(
 
 
 /**
- * scic_cb_port_link_up() - This callback method informs the user that a phy
+ * isci_event_port_link_up() - This callback method informs the user that a phy
  *    has become operational and is capable of communicating with the remote
  *    end point.
  * @controller: This parameter represents the controller associated with the
@@ -435,7 +434,7 @@ void scic_cb_port_bc_change_primitive_received(
  *
  * none.
  */
-void scic_cb_port_link_up(
+void isci_event_port_link_up(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	struct scic_sds_phy *phy)
@@ -452,7 +451,7 @@ void scic_cb_port_link_up(
 }
 
 /**
- * scic_cb_port_link_down() - This callback method informs the user that a phy
+ * isci_event_port_link_down() - This callback method informs the user that a phy
  *    is no longer operational and is not capable of communicating with the
  *    remote end point.
  * @controller: This parameter represents the controller associated with the
@@ -465,7 +464,7 @@ void scic_cb_port_link_up(
  *
  * none.
  */
-void scic_cb_port_link_down(
+void isci_event_port_link_down(
 	struct scic_sds_controller *controller,
 	struct scic_sds_port *port,
 	struct scic_sds_phy *phy)
@@ -490,7 +489,7 @@ void scic_cb_port_link_down(
 }
 
 /**
- * scic_cb_remote_device_start_complete() - This user callback method will
+ * isci_event_remote_device_start_complete() - This user callback method will
  *    inform the user that a start operation has completed.
  * @controller: This parameter specifies the core controller associated with
  *    the completion callback.
@@ -500,7 +499,7 @@ void scic_cb_port_link_down(
  *    operation.
  *
  */
-void scic_cb_remote_device_start_complete(
+void isci_event_remote_device_start_complete(
 	struct scic_sds_controller *controller,
 	struct scic_sds_remote_device *remote_device,
 	enum sci_status completion_status)
@@ -525,9 +524,9 @@ void scic_cb_remote_device_start_complete(
 }
 
 /**
- * scic_cb_remote_device_stop_complete() - This user callback method will
+ * isci_event_remote_device_stop_complete() - This user callback method will
  *    inform the user that a stop operation has completed.
- * @controller: This parameter specifies the core controller associated with
+ * @scic: This parameter specifies the core controller associated with
  *    the completion callback.
  * @remote_device: This parameter specifies the remote device associated with
  *    the completion callback.
@@ -535,32 +534,24 @@ void scic_cb_remote_device_start_complete(
  *    operation.
  *
  */
-void scic_cb_remote_device_stop_complete(
-	struct scic_sds_controller *controller,
-	struct scic_sds_remote_device *remote_device,
-	enum sci_status completion_status)
+void isci_event_remote_device_stop_complete(struct scic_sds_controller *scic,
+					    struct scic_sds_remote_device *sci_dev,
+					    enum sci_status completion_status)
 {
-	struct isci_host *isci_host;
-	struct isci_remote_device *isci_device;
-
-	isci_host =
-		(struct isci_host *)sci_object_get_association(controller);
-
-	isci_device =
-		(struct isci_remote_device *)sci_object_get_association(
-			remote_device
-			);
+	struct isci_host *ihost;
+	struct isci_remote_device *idev;
 
-	dev_dbg(&isci_host->pdev->dev,
-		"%s: isci_device = %p\n", __func__, isci_device);
+	ihost = sci_object_get_association(scic);
+	idev = sci_object_get_association(sci_dev);
 
-	isci_remote_device_stop_complete(
-		isci_host, isci_device, completion_status);
+	dev_dbg(&ihost->pdev->dev,
+		"%s: idev = %p\n", __func__, idev);
 
+	isci_remote_device_stop_complete(ihost, idev, completion_status);
 }
 
 /**
- * scic_cb_remote_device_ready() - This user callback method will inform the
+ * isci_event_remote_device_ready() - This user callback method will inform the
  *    user that a remote device is now capable of handling IO requests.
  * @controller: This parameter specifies the core controller associated with
  *    the completion callback.
@@ -568,7 +559,7 @@ void scic_cb_remote_device_stop_complete(
  *    the callback.
  *
  */
-void scic_cb_remote_device_ready(
+void isci_event_remote_device_ready(
 	struct scic_sds_controller *controller,
 	struct scic_sds_remote_device *remote_device)
 {
@@ -583,7 +574,7 @@ void scic_cb_remote_device_ready(
 }
 
 /**
- * scic_cb_remote_device_not_ready() - This user callback method will inform
+ * isci_event_remote_device_not_ready() - This user callback method will inform
  *    the user that a remote device is no longer capable of handling IO
  *    requests (until a ready callback is invoked).
  * @controller: This parameter specifies the core controller associated with
@@ -594,7 +585,7 @@ void scic_cb_remote_device_ready(
  *    going to a not ready state.
  *
  */
-void scic_cb_remote_device_not_ready(
+void isci_event_remote_device_not_ready(
 	struct scic_sds_controller *controller,
 	struct scic_sds_remote_device *remote_device,
 	u32 reason_code)
diff --git a/drivers/scsi/isci/events.h b/drivers/scsi/isci/events.h
new file mode 100644
index 0000000..fa2f6aa
--- /dev/null
+++ b/drivers/scsi/isci/events.h
@@ -0,0 +1,373 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ISCI_EVENT_H_
+#define _ISCI_EVENT_H_
+
+/**
+ * isci_event_timer_create() - This callback method asks the user to create a
+ *    timer and provide a handle for this timer for use in further timer
+ *    interactions.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to be associated.
+ * @timer_callback: This parameter specifies the callback method to be invoked
+ *    whenever the timer expires.
+ * @cookie: This parameter specifies a piece of information that the user must
+ *    retain.  This cookie is to be supplied by the user anytime a timeout
+ *    occurs for the created timer.
+ *
+ * The "timer_callback" method should be executed in a mutually exlusive manner
+ * from the controller completion handler handler. This method returns a handle
+ * to a timer object created by the user.  The handle will be utilized for all
+ * further interactions relating to this timer.
+ */
+void *isci_event_timer_create(
+	struct scic_sds_controller *controller,
+	void (*timer_callback)(void *),
+	void *cookie);
+
+/**
+ * isci_event_timer_start() - This callback method asks the user to start the
+ *    supplied timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be started.
+ * @milliseconds: This parameter specifies the number of milliseconds for which
+ *    to stall.  The operating system driver is allowed to round this value up
+ *    where necessary.
+ *
+ * All timers in the system started by the SCI Core are one shot timers.
+ * Therefore, the SCI user should make sure that it removes the timer from it's
+ * list when a timer actually fires. Additionally, SCI Core user's should be
+ * able to handle calls from the SCI Core to stop a timer that may already be
+ * stopped. none
+ */
+void isci_event_timer_start(
+	struct scic_sds_controller *controller,
+	void *timer,
+	u32 milliseconds);
+
+/**
+ * isci_event_timer_stop() - This callback method asks the user to stop the
+ *    supplied timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be stopped.
+ *
+ */
+void isci_event_timer_stop(
+	struct scic_sds_controller *controller,
+	void *timer);
+
+
+void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer);
+
+/**
+ * isci_event_controller_start_complete() - This user callback will inform the
+ *    user that the controller has finished the start process.
+ * @controller: This parameter specifies the controller that was started.
+ * @completion_status: This parameter specifies the results of the start
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void isci_event_controller_start_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_controller_stop_complete() - This user callback will inform the
+ * user that the controller has finished the stop process.
+ * @controller: This parameter specifies the controller that was stopped.
+ * @completion_status: This parameter specifies the results of the stop
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void isci_event_controller_stop_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_io_request_complete() - This user callback will inform the user
+ * that an IO request has completed.
+ * @controller: This parameter specifies the controller on which the IO is
+ *    completing.
+ * @remote_device: This parameter specifies the remote device on which this IO
+ *    request is completing.
+ * @io_request: This parameter specifies the IO request that has completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void isci_event_io_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *scic_io_request,
+	enum sci_io_status completion_status);
+
+/**
+ * isci_event_task_request_complete() - This user callback will inform the user
+ *    that a task management request completed.
+ * @controller: This parameter specifies the controller on which the task
+ *    management request is completing.
+ * @remote_device: This parameter specifies the remote device on which this
+ *    task management request is completing.
+ * @task_request: This parameter specifies the task management request that has
+ *    completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void isci_event_task_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *scic_task_request,
+	enum sci_task_status completion_status);
+
+/**
+ * isci_event_port_stop_complete() - This method informs the user when a stop
+ *    operation on the port has completed.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void isci_event_port_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_port_hard_reset_complete() - This method informs the user when a
+ *    hard reset on the port has completed.  This hard reset could have been
+ *    initiated by the user or by the remote port.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void isci_event_port_hard_reset_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_port_ready() - This method informs the user that the port is now
+ * in a ready state and can be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ *
+ */
+void isci_event_port_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port);
+
+/**
+ * isci_event_port_not_ready() - This method informs the user that the port is
+ * now not in a ready (i.e. busy) state and can't be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @reason_code: This parameter specifies the reason for the port not ready
+ *    callback.
+ *
+ */
+void isci_event_port_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	u32 reason_code);
+
+/**
+ * isci_event_port_invalid_link_up() - This method informs the SCI Core user
+ * that a phy/link became ready, but the phy is not allowed in the port.  In
+ * some situations the underlying hardware only allows for certain phy to port
+ *    mappings.  If these mappings are violated, then this API is invoked.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @phy: This parameter specifies the phy that came ready, but the phy can't be
+ *    a valid member of the port.
+ *
+ */
+void isci_event_port_invalid_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * isci_event_port_bc_change_primitive_received() - This callback method informs
+ *    the user that a broadcast change primitive was received.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.  For instances where the phy on which the primitive was
+ *    received is not part of a port, this parameter will be
+ *    NULL.
+ * @phy: This parameter specifies the phy on which the primitive was received.
+ *
+ */
+void isci_event_port_bc_change_primitive_received(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * isci_event_port_link_up() - This callback method informs the user that a phy
+ *    has become operational and is capable of communicating with the remote
+ *    end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    NULL
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ */
+void isci_event_port_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * isci_event_port_link_down() - This callback method informs the user that a
+ * phy is no longer operational and is not capable of communicating with the
+ *    remote end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    NULL
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ */
+void isci_event_port_link_down(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * isci_event_remote_device_start_complete() - This user callback method will
+ *    inform the user that a start operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void isci_event_remote_device_start_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_remote_device_stop_complete() - This user callback method will
+ *    inform the user that a stop operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void isci_event_remote_device_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status);
+
+/**
+ * isci_event_remote_device_ready() - This user callback method will inform the
+ *    user that a remote device is now capable of handling IO requests.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ *
+ */
+void isci_event_remote_device_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device);
+
+/**
+ * isci_event_remote_device_not_ready() - This user callback method will inform
+ *    the user that a remote device is no longer capable of handling IO
+ *    requests (until a ready callback is invoked).
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ * @reason_code: This paramete specifies the reason the remote device is not
+ *    ready.
+ *
+ */
+void isci_event_remote_device_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	u32 reason_code);
+
+#endif
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index aa86615..dc231c2 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -78,8 +78,9 @@ irqreturn_t isci_intx_isr(int vec, void *data)
 	struct pci_dev *pdev = data;
 	struct isci_host *ihost;
 	irqreturn_t ret = IRQ_NONE;
+	int i;
 
-	for_each_isci_host(ihost, pdev) {
+	for_each_isci_host(i, ihost, pdev) {
 		struct scic_sds_controller *scic = ihost->core_controller;
 
 		if (scic_sds_controller_isr(scic)) {
@@ -269,27 +270,29 @@ static int isci_host_mdl_allocate_coherent(
 static void isci_host_completion_routine(unsigned long data)
 {
 	struct isci_host *isci_host = (struct isci_host *)data;
-	struct list_head completed_request_list;
-	struct list_head aborted_request_list;
-	struct list_head *current_position;
-	struct list_head *next_position;
+	struct list_head    completed_request_list;
+	struct list_head    errored_request_list;
+	struct list_head    *current_position;
+	struct list_head    *next_position;
 	struct isci_request *request;
 	struct isci_request *next_request;
-	struct sas_task *task;
+	struct sas_task     *task;
 
 	INIT_LIST_HEAD(&completed_request_list);
-	INIT_LIST_HEAD(&aborted_request_list);
+	INIT_LIST_HEAD(&errored_request_list);
 
 	spin_lock_irq(&isci_host->scic_lock);
 
 	scic_sds_controller_completion_handler(isci_host->core_controller);
 
 	/* Take the lists of completed I/Os from the host. */
+
 	list_splice_init(&isci_host->requests_to_complete,
 			 &completed_request_list);
 
-	list_splice_init(&isci_host->requests_to_abort,
-			 &aborted_request_list);
+	/* Take the list of errored I/Os from the host. */
+	list_splice_init(&isci_host->requests_to_errorback,
+			 &errored_request_list);
 
 	spin_unlock_irq(&isci_host->scic_lock);
 
@@ -308,13 +311,22 @@ static void isci_host_completion_routine(unsigned long data)
 			request,
 			task);
 
-		task->task_done(task);
-		task->lldd_task = NULL;
+		/* Return the task to libsas */
+		if (task != NULL) {
 
+			task->lldd_task = NULL;
+			if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+
+				/* If the task is already in the abort path,
+				* the task_done callback cannot be called.
+				*/
+				task->task_done(task);
+			}
+		}
 		/* Free the request object. */
 		isci_request_free(isci_host, request);
 	}
-	list_for_each_entry_safe(request, next_request, &aborted_request_list,
+	list_for_each_entry_safe(request, next_request, &errored_request_list,
 				 completed_node) {
 
 		task = isci_request_access_task(request);
@@ -326,8 +338,33 @@ static void isci_host_completion_routine(unsigned long data)
 			 request,
 			 task);
 
-		/* Put the task into the abort path. */
-		sas_task_abort(task);
+		if (task != NULL) {
+
+			/* Put the task into the abort path if it's not there
+			 * already.
+			 */
+			if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED))
+				sas_task_abort(task);
+
+		} else {
+			/* This is a case where the request has completed with a
+			 * status such that it needed further target servicing,
+			 * but the sas_task reference has already been removed
+			 * from the request.  Since it was errored, it was not
+			 * being aborted, so there is nothing to do except free
+			 * it.
+			 */
+
+			spin_lock_irq(&isci_host->scic_lock);
+			/* Remove the request from the remote device's list
+			* of pending requests.
+			*/
+			list_del_init(&request->dev_node);
+			spin_unlock_irq(&isci_host->scic_lock);
+
+			/* Free the request object. */
+			isci_request_free(isci_host, request);
+		}
 	}
 
 }
@@ -344,14 +381,19 @@ void isci_host_deinit(struct isci_host *ihost)
 
 		list_for_each_entry_safe(idev, d, &port->remote_dev_list, node) {
 			isci_remote_device_change_state(idev, isci_stopping);
-			isci_remote_device_stop(idev);
+			isci_remote_device_stop(ihost, idev);
 		}
 	}
 
 	set_bit(IHOST_STOP_PENDING, &ihost->flags);
+
+	spin_lock_irq(&ihost->scic_lock);
 	scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT);
+	spin_unlock_irq(&ihost->scic_lock);
+
 	wait_for_stop(ihost);
 	scic_controller_reset(scic);
+	isci_timer_list_destroy(ihost);
 }
 
 static void __iomem *scu_base(struct isci_host *isci_host)
@@ -370,23 +412,15 @@ static void __iomem *smu_base(struct isci_host *isci_host)
 	return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
 }
 
-#define SCI_MAX_TIMER_COUNT 25
-
 int isci_host_init(struct isci_host *isci_host)
 {
-	int err = 0;
-	int index = 0;
+	int err = 0, i;
 	enum sci_status status;
 	struct scic_sds_controller *controller;
-	struct scic_sds_port *scic_port;
 	union scic_oem_parameters scic_oem_params;
 	union scic_user_parameters scic_user_params;
 
-	INIT_LIST_HEAD(&isci_host->timer_list_struct.timers);
-	isci_timer_list_construct(
-		&isci_host->timer_list_struct,
-		SCI_MAX_TIMER_COUNT
-		);
+	isci_timer_list_construct(isci_host);
 
 	controller = scic_controller_alloc(&isci_host->pdev->dev);
 
@@ -473,7 +507,17 @@ int isci_host_init(struct isci_host *isci_host)
 		}
 	}
 
+	tasklet_init(&isci_host->completion_tasklet,
+		     isci_host_completion_routine, (unsigned long)isci_host);
+
+	INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
+
+	INIT_LIST_HEAD(&isci_host->requests_to_complete);
+	INIT_LIST_HEAD(&isci_host->requests_to_errorback);
+
+	spin_lock_irq(&isci_host->scic_lock);
 	status = scic_controller_initialize(isci_host->core_controller);
+	spin_unlock_irq(&isci_host->scic_lock);
 	if (status != SCI_SUCCESS) {
 		dev_warn(&isci_host->pdev->dev,
 			 "%s: scic_controller_initialize failed -"
@@ -482,17 +526,8 @@ int isci_host_init(struct isci_host *isci_host)
 		return -ENODEV;
 	}
 
-	tasklet_init(&isci_host->completion_tasklet,
-		     isci_host_completion_routine, (unsigned long)isci_host);
-
-	INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
-
-	INIT_LIST_HEAD(&isci_host->requests_to_complete);
-	INIT_LIST_HEAD(&isci_host->requests_to_abort);
-
 	/* populate mdl with dma memory. scu_mdl_allocate_coherent() */
 	err = isci_host_mdl_allocate_coherent(isci_host);
-
 	if (err)
 		return err;
 
@@ -509,23 +544,18 @@ int isci_host_init(struct isci_host *isci_host)
 	if (!isci_host->dma_pool)
 		return -ENOMEM;
 
-	for (index = 0; index < SCI_MAX_PORTS; index++)
-		isci_port_init(&isci_host->isci_ports[index],
-			       isci_host,
-			       index);
+	for (i = 0; i < SCI_MAX_PORTS; i++)
+		isci_port_init(&isci_host->isci_ports[i], isci_host, i);
 
-	for (index = 0; index < SCI_MAX_PHYS; index++)
-		isci_phy_init(&isci_host->phys[index], isci_host, index);
+	for (i = 0; i < SCI_MAX_PHYS; i++)
+		isci_phy_init(&isci_host->phys[i], isci_host, i);
 
-	/* Why are we doing this? Is this even necessary? */
-	memcpy(&isci_host->sas_addr[0],
-	       &isci_host->phys[0].sas_addr[0],
-	       SAS_ADDR_SIZE);
+	for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+		struct isci_remote_device *idev = idev_by_id(isci_host, i);
 
-	/* Start the ports */
-	for (index = 0; index < SCI_MAX_PORTS; index++) {
-		scic_controller_get_port_handle(controller, index, &scic_port);
-		scic_port_start(scic_port);
+		INIT_LIST_HEAD(&idev->reqs_in_process);
+		INIT_LIST_HEAD(&idev->node);
+		spin_lock_init(&idev->state_lock);
 	}
 
 	return 0;
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 26768c5..889a785 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -61,7 +61,7 @@
 /*#include "task.h"*/
 #include "timers.h"
 #include "remote_device.h"
-#include "scic_user_callback.h"
+#include "scic_remote_device.h"
 
 #define DRV_NAME "isci"
 #define SCI_PCI_BAR_COUNT 2
@@ -88,7 +88,7 @@ struct isci_host {
 	union scic_oem_parameters oem_parameters;
 
 	int id; /* unique within a given pci device */
-	struct isci_timer_list timer_list_struct;
+	struct list_head timers;
 	void *core_ctrl_memory;
 	struct dma_pool *dma_pool;
 	unsigned int dma_pool_alloc_size;
@@ -106,7 +106,6 @@ struct isci_host {
 	spinlock_t state_lock;
 
 	struct pci_dev *pdev;
-	u8 sas_addr[SAS_ADDR_SIZE];
 
 	enum isci_status status;
 	#define IHOST_START_PENDING 0
@@ -117,11 +116,20 @@ struct isci_host {
 	struct tasklet_struct completion_tasklet;
 	struct list_head mdl_struct_list;
 	struct list_head requests_to_complete;
-	struct list_head requests_to_abort;
+	struct list_head requests_to_errorback;
 	spinlock_t scic_lock;
-	struct isci_host *next;
+
+	/* careful only access this via idev_by_id */
+	struct isci_remote_device devices[0];
 };
 
+static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int i)
+{
+	void *p = ihost->devices;
+
+	return p + i * (sizeof(struct isci_remote_device) +
+			scic_remote_device_get_object_size());
+}
 
 /**
  * struct isci_pci_info - This class represents the pci function containing the
@@ -133,7 +141,7 @@ struct isci_host {
 struct isci_pci_info {
 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
 	int core_lib_array_index;
-	struct isci_host *hosts;
+	struct isci_host *hosts[SCI_MAX_CONTROLLERS];
 };
 
 static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
@@ -141,9 +149,10 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
 	return pci_get_drvdata(pdev);
 }
 
-#define for_each_isci_host(isci_host, pdev) \
-	for (isci_host = to_pci_info(pdev)->hosts;\
-	     isci_host; isci_host = isci_host->next)
+#define for_each_isci_host(id, ihost, pdev) \
+	for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
+	     id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
+	     ihost = to_pci_info(pdev)->hosts[++id])
 
 static inline
 enum isci_status isci_host_get_state(
@@ -214,6 +223,15 @@ static inline void wait_for_stop(struct isci_host *ihost)
 	wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
 }
 
+static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev)
+{
+	wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags));
+}
+
+static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
+{
+	wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
+}
 
 /**
  * isci_host_from_sas_ha() - This accessor retrieves the isci_host object
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index a5467cf..500c0b5 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -64,7 +64,6 @@
 #include "sci_environment.h"
 
 static struct scsi_transport_template *isci_transport_template;
-struct kmem_cache *isci_kmem_cache;
 
 static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
 	{ PCI_VDEVICE(INTEL, 0x1D61),},
@@ -213,7 +212,7 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
 
 	sas_ha->sas_ha_name = DRV_NAME;
 	sas_ha->lldd_module = THIS_MODULE;
-	sas_ha->sas_addr    = &(isci_host->sas_addr[0]);
+	sas_ha->sas_addr    = &isci_host->phys[0].sas_addr[0];
 
 	/* set the array of phy and port structs.  */
 	for (i = 0; i < SCI_MAX_PHYS; i++) {
@@ -234,12 +233,28 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
 	return 0;
 }
 
-static void isci_unregister_sas_ha(struct isci_host *isci_host)
+static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
+	struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
+	struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+	struct isci_host *ihost = container_of(sas_ha, typeof(*ihost), sas_ha);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ihost->id);
+}
+
+static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL);
+
+static void isci_unregister(struct isci_host *isci_host)
+{
+	struct Scsi_Host *shost;
+
 	if (!isci_host)
 		return;
 
-	sas_unregister_ha(&(isci_host->sas_ha));
+	shost = isci_host->shost;
+	device_remove_file(&shost->shost_dev, &dev_attr_isci_id);
+
+	sas_unregister_ha(&isci_host->sas_ha);
 
 	sas_remove_host(isci_host->shost);
 	scsi_remove_host(isci_host->shost);
@@ -289,16 +304,6 @@ static int __devinit isci_pci_init(struct pci_dev *pdev)
 	return 0;
 }
 
-static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id)
-{
-	struct isci_host *h;
-
-	for_each_isci_host(h, pdev)
-		if (h->id == id)
-			return h;
-	return NULL;
-}
-
 static int num_controllers(struct pci_dev *pdev)
 {
 	/* bar size alone can tell us if we are running with a dual controller
@@ -336,7 +341,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
 	for (i = 0; i < num_msix; i++) {
 		int id = i / SCI_NUM_MSI_X_INT;
 		struct msix_entry *msix = &pci_info->msix_entries[i];
-		struct isci_host *isci_host = isci_host_by_id(pdev, id);
+		struct isci_host *isci_host = pci_info->hosts[id];
 		irq_handler_t isr;
 
 		/* odd numbered vectors are error interrupts */
@@ -355,7 +360,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
 		dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
 		while (i--) {
 			id = i / SCI_NUM_MSI_X_INT;
-			isci_host = isci_host_by_id(pdev, id);
+			isci_host = pci_info->hosts[id];
 			msix = &pci_info->msix_entries[i];
 			devm_free_irq(&pdev->dev, msix->vector, isci_host);
 		}
@@ -457,7 +462,10 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
 	struct Scsi_Host *shost;
 	int err;
 
-	isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
+	isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) +
+				 SCI_MAX_REMOTE_DEVICES *
+				 (sizeof(struct isci_remote_device) +
+				  scic_remote_device_get_object_size()), GFP_KERNEL);
 	if (!isci_host)
 		return NULL;
 
@@ -489,8 +497,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
 	if (err)
 		goto err_shost_remove;
 
+	err = device_create_file(&shost->shost_dev, &dev_attr_isci_id);
+	if (err)
+		goto err_unregister_ha;
+
 	return isci_host;
 
+ err_unregister_ha:
+	sas_unregister_ha(&(isci_host->sas_ha));
  err_shost_remove:
 	scsi_remove_host(shost);
  err_shost:
@@ -638,32 +652,31 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
 			err = -ENOMEM;
 			goto err_host_alloc;
 		}
-
-		h->next = pci_info->hosts;
-		pci_info->hosts = h;
+		pci_info->hosts[i] = h;
 	}
 
 	err = isci_setup_interrupts(pdev);
 	if (err)
 		goto err_host_alloc;
 
-	for_each_isci_host(isci_host, pdev)
+	for_each_isci_host(i, isci_host, pdev)
 		scsi_scan_host(isci_host->shost);
 
 	return 0;
 
  err_host_alloc:
-	for_each_isci_host(isci_host, pdev)
-		isci_unregister_sas_ha(isci_host);
+	for_each_isci_host(i, isci_host, pdev)
+		isci_unregister(isci_host);
 	return err;
 }
 
 static void __devexit isci_pci_remove(struct pci_dev *pdev)
 {
 	struct isci_host *isci_host;
+	int i;
 
-	for_each_isci_host(isci_host, pdev) {
-		isci_unregister_sas_ha(isci_host);
+	for_each_isci_host(i, isci_host, pdev) {
+		isci_unregister(isci_host);
 		isci_host_deinit(isci_host);
 		scic_controller_disable_interrupts(isci_host->core_controller);
 	}
@@ -671,31 +684,17 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev)
 
 static __init int isci_init(void)
 {
-	int err = -ENOMEM;
+	int err;
 
 	pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
 
-	isci_kmem_cache = kmem_cache_create(DRV_NAME,
-					    sizeof(struct isci_remote_device) +
-					    scic_remote_device_get_object_size(),
-					    0, 0, NULL);
-	if (!isci_kmem_cache)
-		return err;
-
 	isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
 	if (!isci_transport_template)
-		goto err_kmem;
+		return -ENOMEM;
 
 	err = pci_register_driver(&isci_pci_driver);
 	if (err)
-		goto err_sas;
-
-	return 0;
-
- err_sas:
-	sas_release_transport(isci_transport_template);
- err_kmem:
-	kmem_cache_destroy(isci_kmem_cache);
+		sas_release_transport(isci_transport_template);
 
 	return err;
 }
@@ -704,7 +703,6 @@ static __exit void isci_exit(void)
 {
 	pci_unregister_driver(&isci_pci_driver);
 	sas_release_transport(isci_transport_template);
-	kmem_cache_destroy(isci_kmem_cache);
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 6c79b29..b3f63f1 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -53,21 +53,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/**
- * This file contains the isci_module object definition.
- *
- * isci.h
- */
-
-#if !defined(_SCI_MODULE_H_)
-#define _SCI_MODULE_H_
-
-/**
- * This file contains the SCI low level driver interface to the SCI and Libsas
- *    Libraries.
- *
- * isci.h
- */
+#ifndef __ISCI_H__
+#define __ISCI_H__
 
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -84,8 +71,11 @@
 #include "host.h"
 #include "timers.h"
 #include "sci_status.h"
+#include "request.h"
+#include "events.h"
+#include "task.h"
+#include "sata.h"
 
-extern struct kmem_cache *isci_kmem_cache;
 extern struct isci_firmware *isci_firmware;
 
 #define ISCI_FW_NAME		"isci/isci_firmware.bin"
@@ -133,11 +123,4 @@ enum sci_status isci_parse_user_parameters(
 	int scu_index,
 	struct isci_firmware *fw);
 
-#ifdef ISCI_SLAVE_ALLOC
-extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev);
-#endif /* ISCI_SLAVE_ALLOC */
-
-#ifdef ISCI_SLAVE_DESTROY
-extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev);
-#endif  /* ISCI_SLAVE_DESTROY */
-#endif  /* !defined(_SCI_MODULE_H_) */
+#endif  /* __ISCI_H__ */
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index fbda570..decc0c0 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -58,6 +58,9 @@
 #include "scic_port.h"
 #include "scic_config_parameters.h"
 
+struct scic_sds_phy;
+extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy);
+extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy);
 
 /**
  * isci_phy_init() - This function is called by the probe function to
@@ -75,14 +78,15 @@ void isci_phy_init(
 	struct isci_host *isci_host,
 	int index)
 {
-	struct scic_sds_controller *controller = isci_host->core_controller;
+	struct scic_sds_controller *scic = isci_host->core_controller;
 	struct scic_sds_phy *scic_phy;
-	union scic_oem_parameters oem_parameters;
+	union scic_oem_parameters oem;
 	enum sci_status status = SCI_SUCCESS;
+	u64 sas_addr;
 
 	/*--------------- SCU_Phy Initialization Stuff -----------------------*/
 
-	status = scic_controller_get_phy_handle(controller, index, &scic_phy);
+	status = scic_controller_get_phy_handle(scic, index, &scic_phy);
 	if (status == SCI_SUCCESS) {
 		sci_object_set_association(scic_phy, (void *)phy);
 		phy->sci_phy_handle = scic_phy;
@@ -90,24 +94,13 @@ void isci_phy_init(
 		dev_err(&isci_host->pdev->dev,
 			"failed scic_controller_get_phy_handle\n");
 
-	scic_oem_parameters_get(controller, &oem_parameters);
-
-	phy->sas_addr[0] =  oem_parameters.sds1.phys[index].sas_address.low
-			   & 0xFF;
-	phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low
-			    >> 8)   & 0xFF;
-	phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low
-			    >> 16)  & 0xFF;
-	phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low
-			    >> 24)  & 0xFF;
-	phy->sas_addr[4] =  oem_parameters.sds1.phys[index].sas_address.high
-			   & 0xFF;
-	phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high
-			    >> 8)  & 0xFF;
-	phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high
-			    >> 16) & 0xFF;
-	phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high
-			    >> 24) & 0xFF;
+	scic_oem_parameters_get(scic, &oem);
+	sas_addr = oem.sds1.phys[index].sas_address.high;
+	sas_addr <<= 32;
+	sas_addr |= oem.sds1.phys[index].sas_address.low;
+	swab64s(&sas_addr);
+
+	memcpy(phy->sas_addr, &sas_addr, sizeof(sas_addr));
 
 	phy->isci_port = NULL;
 	phy->sas_phy.enabled = 0;
@@ -137,42 +130,48 @@ void isci_phy_init(
  *
  * status, zero indicates success.
  */
-int isci_phy_control(
-	struct asd_sas_phy *phy,
-	enum phy_func func,
-	void *buf)
+int isci_phy_control(struct asd_sas_phy *sas_phy,
+		     enum phy_func func,
+		     void *buf)
 {
-	int ret            = TMF_RESP_FUNC_COMPLETE;
-	struct isci_phy *isci_phy_ptr  = (struct isci_phy *)phy->lldd_phy;
-	struct isci_port *isci_port_ptr = NULL;
-
-	if (isci_phy_ptr != NULL)
-		isci_port_ptr = isci_phy_ptr->isci_port;
-
-	if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) {
-		pr_err("%s: asd_sas_phy %p: lldd_phy %p or "
-		       "isci_port %p == NULL!\n",
-		       __func__, phy, isci_phy_ptr, isci_port_ptr);
-		return TMF_RESP_FUNC_FAILED;
-	}
+	int ret = 0;
+	struct isci_phy *iphy = sas_phy->lldd_phy;
+	struct isci_port *iport = iphy->isci_port;
+	struct isci_host *ihost = sas_phy->ha->lldd_ha;
+	unsigned long flags;
 
-	pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
-		 __func__, phy, func, buf, isci_phy_ptr, isci_port_ptr);
+	dev_dbg(&ihost->pdev->dev,
+		"%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
+		__func__, sas_phy, func, buf, iphy, iport);
 
 	switch (func) {
-	case PHY_FUNC_HARD_RESET:
+	case PHY_FUNC_DISABLE:
+		spin_lock_irqsave(&ihost->scic_lock, flags);
+		scic_sds_phy_stop(iphy->sci_phy_handle);
+		spin_unlock_irqrestore(&ihost->scic_lock, flags);
+		break;
+
 	case PHY_FUNC_LINK_RESET:
+		spin_lock_irqsave(&ihost->scic_lock, flags);
+		scic_sds_phy_stop(iphy->sci_phy_handle);
+		scic_sds_phy_start(iphy->sci_phy_handle);
+		spin_unlock_irqrestore(&ihost->scic_lock, flags);
+		break;
+
+	case PHY_FUNC_HARD_RESET:
+		if (!iport)
+			return -ENODEV;
 
 		/* Perform the port reset. */
-		ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr);
+		ret = isci_port_perform_hard_reset(iport, iphy);
 
 		break;
 
-	case PHY_FUNC_DISABLE:
 	default:
-		pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n",
-			 __func__, phy, func);
-		ret = TMF_RESP_FUNC_FAILED;
+		dev_dbg(&ihost->pdev->dev,
+			   "%s: phy %p; func %d NOT IMPLEMENTED!\n",
+			   __func__, sas_phy, func);
+		ret = -ENOSYS;
 		break;
 	}
 	return ret;
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 446da20..a5b2565 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -94,7 +94,6 @@ void isci_port_init(
 
 	INIT_LIST_HEAD(&isci_port->remote_dev_list);
 	INIT_LIST_HEAD(&isci_port->domain_dev_list);
-	spin_lock_init(&isci_port->remote_device_lock);
 	spin_lock_init(&isci_port->state_lock);
 	init_completion(&isci_port->start_complete);
 	isci_port->isci_host = isci_host;
@@ -192,6 +191,7 @@ void isci_port_link_up(
 	scic_port_get_properties(port, &properties);
 
 	if (properties.remote.protocols.u.bits.stp_target) {
+		u64 attached_sas_address;
 
 		struct scic_sata_phy_properties sata_phy_properties;
 
@@ -220,17 +220,13 @@ void isci_port_link_up(
 		 * will not be the same as assigned to the PHY and needs
 		 * to be obtained from struct scic_port_properties properties.
 		 */
+		attached_sas_address = properties.remote.sas_address.high;
+		attached_sas_address <<= 32;
+		attached_sas_address |= properties.remote.sas_address.low;
+		swab64s(&attached_sas_address);
 
-		BUG_ON(((size_t)SAS_ADDR_SIZE / 2)
-		       != sizeof(properties.remote.sas_address.low));
-
-		memcpy(&isci_phy->sas_phy.attached_sas_addr[0],
-		       &properties.remote.sas_address.low,
-		       SAS_ADDR_SIZE / 2);
-
-		memcpy(&isci_phy->sas_phy.attached_sas_addr[4],
-		       &properties.remote.sas_address.high,
-		       SAS_ADDR_SIZE / 2);
+		memcpy(&isci_phy->sas_phy.attached_sas_addr,
+		       &attached_sas_address, sizeof(attached_sas_address));
 
 	} else if (properties.remote.protocols.u.bits.ssp_target ||
 		   properties.remote.protocols.u.bits.smp_target) {
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index b01b0c6..b7a7dd7 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -73,7 +73,6 @@ enum isci_status {
 	isci_ready_for_io = 0x03,
 	isci_stopping     = 0x04,
 	isci_stopped      = 0x05,
-	isci_host_quiesce = 0x06
 };
 
 /**
@@ -91,7 +90,6 @@ struct isci_port {
 	struct isci_host *isci_host;
 	struct asd_sas_port sas_port;
 	struct list_head remote_dev_list;
-	spinlock_t remote_device_lock;
 	spinlock_t state_lock;
 	struct list_head domain_dev_list;
 	struct completion start_complete;
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index dec9033..6fe6815 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -67,35 +67,35 @@
 
 /**
  * isci_remote_device_deconstruct() - This function frees an isci_remote_device.
- * @isci_host: This parameter specifies the isci host object.
- * @isci_device: This parameter specifies the remote device to be freed.
+ * @ihost: This parameter specifies the isci host object.
+ * @idev: This parameter specifies the remote device to be freed.
  *
  */
-static void isci_remote_device_deconstruct(
-	struct isci_host *isci_host,
-	struct isci_remote_device *isci_device)
+static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev)
 {
-	dev_dbg(&isci_host->pdev->dev,
-		"%s: isci_device = %p\n", __func__, isci_device);
+	dev_dbg(&ihost->pdev->dev,
+		"%s: isci_device = %p\n", __func__, idev);
 
 	/* There should not be any outstanding io's. All paths to
 	 * here should go through isci_remote_device_nuke_requests.
 	 * If we hit this condition, we will need a way to complete
 	 * io requests in process */
-	while (!list_empty(&isci_device->reqs_in_process)) {
+	while (!list_empty(&idev->reqs_in_process)) {
 
-		dev_err(&isci_host->pdev->dev,
+		dev_err(&ihost->pdev->dev,
 			"%s: ** request list not empty! **\n", __func__);
 		BUG();
 	}
 
-	/* Remove all related references to this device and free
-	 * the cache object.
-	 */
-	scic_remote_device_destruct(isci_device->sci_device_handle);
-	isci_device->domain_dev->lldd_dev = NULL;
-	list_del(&isci_device->node);
-	kmem_cache_free(isci_kmem_cache, isci_device);
+	scic_remote_device_destruct(to_sci_dev(idev));
+	idev->domain_dev->lldd_dev = NULL;
+	idev->domain_dev = NULL;
+	idev->isci_port = NULL;
+	list_del_init(&idev->node);
+
+	clear_bit(IDEV_START_PENDING, &idev->flags);
+	clear_bit(IDEV_STOP_PENDING, &idev->flags);
+	wake_up(&ihost->eventq);
 }
 
 
@@ -117,7 +117,7 @@ static enum sci_status isci_remote_device_construct(
 
 	/* let the core do it's common constuction. */
 	scic_remote_device_construct(port->sci_port_handle,
-				     isci_device->sci_device_handle);
+				     to_sci_dev(isci_device));
 
 	/* let the core do it's device specific constuction. */
 	if (isci_device->domain_dev->parent &&
@@ -183,15 +183,11 @@ static enum sci_status isci_remote_device_construct(
 			"%s: parent->dev_type = EDGE_DEV\n",
 			__func__);
 
-		status = scic_remote_device_ea_construct(
-			isci_device->sci_device_handle,
-			(struct smp_response_discover *)&discover_response
-			);
+		status = scic_remote_device_ea_construct(to_sci_dev(isci_device),
+				(struct smp_response_discover *)&discover_response);
 
 	} else
-		status = scic_remote_device_da_construct(
-			isci_device->sci_device_handle
-			);
+		status = scic_remote_device_da_construct(to_sci_dev(isci_device));
 
 
 	if (status != SCI_SUCCESS) {
@@ -204,18 +200,13 @@ static enum sci_status isci_remote_device_construct(
 		return status;
 	}
 
-	sci_object_set_association(
-		isci_device->sci_device_handle,
-		isci_device
-		);
+	sci_object_set_association(to_sci_dev(isci_device), isci_device);
 
 	BUG_ON(port->isci_host == NULL);
 
 	/* start the device. */
-	status = scic_remote_device_start(
-		isci_device->sci_device_handle,
-		ISCI_REMOTE_DEVICE_START_TIMEOUT
-		);
+	status = scic_remote_device_start(to_sci_dev(isci_device),
+					  ISCI_REMOTE_DEVICE_START_TIMEOUT);
 
 	if (status != SCI_SUCCESS) {
 		dev_warn(&port->isci_host->pdev->dev,
@@ -263,81 +254,46 @@ void isci_remote_device_nuke_requests(
  * pointer to new isci_remote_device.
  */
 static struct isci_remote_device *
-isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port)
+isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
 {
-	struct isci_remote_device *isci_device;
-	struct scic_sds_remote_device *sci_dev;
+	struct isci_remote_device *idev;
+	int i;
 
-	isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL);
+	for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+		idev = idev_by_id(ihost, i);
+		if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags))
+			break;
+	}
 
-	if (!isci_device) {
-		dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__);
+	if (i >= SCI_MAX_REMOTE_DEVICES) {
+		dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__);
 		return NULL;
 	}
 
-	sci_dev = (struct scic_sds_remote_device *) &isci_device[1];
-	isci_device->sci_device_handle = sci_dev;
-	INIT_LIST_HEAD(&isci_device->reqs_in_process);
-	INIT_LIST_HEAD(&isci_device->node);
-	isci_device->host_quiesce          = false;
-
-	spin_lock_init(&isci_device->state_lock);
-	spin_lock_init(&isci_device->host_quiesce_lock);
-	isci_remote_device_change_state(isci_device, isci_freed);
+	BUG_ON(!list_empty(&idev->reqs_in_process));
+	BUG_ON(!list_empty(&idev->node));
+	isci_remote_device_change_state(idev, isci_freed);
 
-	return isci_device;
-
-}
-/**
- * isci_device_set_host_quiesce_lock_state() - This function sets the host I/O
- *    quiesce lock state for the remote_device object.
- * @isci_device,: This parameter points to the isci_remote_device object
- * @isci_device: This parameter specifies the new quiesce state.
- *
- */
-void isci_device_set_host_quiesce_lock_state(
-	struct isci_remote_device *isci_device,
-	bool lock_state)
-{
-	unsigned long flags;
-
-	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
-		"%s: isci_device=%p, lock_state=%d\n",
-		__func__, isci_device, lock_state);
-
-	spin_lock_irqsave(&isci_device->host_quiesce_lock, flags);
-	isci_device->host_quiesce = lock_state;
-	spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags);
+	return idev;
 }
 
 /**
  * isci_remote_device_ready() - This function is called by the scic when the
  *    remote device is ready. We mark the isci device as ready and signal the
  *    waiting proccess.
- * @isci_host: This parameter specifies the isci host object.
- * @isci_device: This parameter specifies the remote device
+ * @idev: This parameter specifies the remote device
  *
  */
-void isci_remote_device_ready(struct isci_remote_device *isci_device)
+void isci_remote_device_ready(struct isci_remote_device *idev)
 {
-	unsigned long flags;
-
-	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
-		"%s: isci_device = %p\n", __func__, isci_device);
+	struct isci_host *ihost = idev->isci_port->isci_host;
 
-	/* device ready is actually a "ready for io" state. */
-	if ((isci_starting == isci_remote_device_get_state(isci_device)) ||
-	    (isci_ready == isci_remote_device_get_state(isci_device))) {
-		spin_lock_irqsave(&isci_device->isci_port->remote_device_lock,
-				  flags);
-		isci_remote_device_change_state(isci_device, isci_ready_for_io);
-		if (isci_device->completion)
-			complete(isci_device->completion);
-		spin_unlock_irqrestore(
-				&isci_device->isci_port->remote_device_lock,
-				flags);
-	}
+	dev_dbg(&ihost->pdev->dev,
+		"%s: idev = %p\n", __func__, idev);
 
+	isci_remote_device_change_state(idev, isci_ready_for_io);
+	if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
+		wake_up(&ihost->eventq);
 }
 
 /**
@@ -376,8 +332,6 @@ void isci_remote_device_stop_complete(
 	struct isci_remote_device *isci_device,
 	enum sci_status status)
 {
-	struct completion *completion = isci_device->completion;
-
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: complete isci_device = %p, status = 0x%x\n",
 		__func__,
@@ -389,9 +343,6 @@ void isci_remote_device_stop_complete(
 	/* after stop, we can tear down resources. */
 	isci_remote_device_deconstruct(isci_host, isci_device);
 
-	/* notify interested parties. */
-	if (completion)
-		complete(completion);
 }
 
 /**
@@ -420,43 +371,35 @@ void isci_remote_device_start_complete(
  *
  * The status of the scic request to stop.
  */
-enum sci_status isci_remote_device_stop(
-	struct isci_remote_device *isci_device)
+enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
 {
 	enum sci_status status;
 	unsigned long flags;
 
-	DECLARE_COMPLETION_ONSTACK(completion);
-
-	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
-		"%s: isci_device = %p\n", __func__, isci_device);
-
-	isci_remote_device_change_state(isci_device, isci_stopping);
+	dev_dbg(&ihost->pdev->dev,
+		"%s: isci_device = %p\n", __func__, idev);
 
-	/* We need comfirmation that stop completed. */
-	isci_device->completion = &completion;
+	isci_remote_device_change_state(idev, isci_stopping);
 
-	BUG_ON(isci_device->isci_port == NULL);
-	BUG_ON(isci_device->isci_port->isci_host == NULL);
+	/* Kill all outstanding requests. */
+	isci_remote_device_nuke_requests(idev);
 
-	spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags);
+	set_bit(IDEV_STOP_PENDING, &idev->flags);
 
-	status = scic_remote_device_stop(
-		isci_device->sci_device_handle,
-		50
-		);
-
-	spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags);
+	spin_lock_irqsave(&ihost->scic_lock, flags);
+	status = scic_remote_device_stop(to_sci_dev(idev), 50);
+	spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
 	/* Wait for the stop complete callback. */
-	if (status == SCI_SUCCESS)
-		wait_for_completion(&completion);
+	if (status == SCI_SUCCESS) {
+		wait_for_device_stop(ihost, idev);
+		clear_bit(IDEV_ALLOCATED, &idev->flags);
+	}
 
-	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
-		"%s: isci_device = %p - after completion wait\n",
-		__func__, isci_device);
+	dev_dbg(&ihost->pdev->dev,
+		"%s: idev = %p - after completion wait\n",
+		__func__, idev);
 
-	isci_device->completion = NULL;
 	return status;
 }
 
@@ -466,18 +409,16 @@ enum sci_status isci_remote_device_stop(
  * @domain_device: This parameter specifies the libsas domain device.
  *
  */
-void isci_remote_device_gone(
-	struct domain_device *domain_dev)
+void isci_remote_device_gone(struct domain_device *dev)
 {
-	struct isci_remote_device *isci_device = isci_dev_from_domain_dev(
-		domain_dev);
+	struct isci_host *ihost = dev->port->ha->lldd_ha;
+	struct isci_remote_device *idev = dev->lldd_dev;
 
-	dev_err(&isci_device->isci_port->isci_host->pdev->dev,
+	dev_dbg(&ihost->pdev->dev,
 		"%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
-		__func__, domain_dev, isci_device, isci_device->isci_port);
+		__func__, dev, idev, idev->isci_port);
 
-	if (isci_device != NULL)
-		isci_remote_device_stop(isci_device);
+	isci_remote_device_stop(ihost, idev);
 }
 
 
@@ -492,7 +433,6 @@ void isci_remote_device_gone(
  */
 int isci_remote_device_found(struct domain_device *domain_dev)
 {
-	unsigned long flags;
 	struct isci_host *isci_host;
 	struct isci_port *isci_port;
 	struct isci_phy *isci_phy;
@@ -500,7 +440,6 @@ int isci_remote_device_found(struct domain_device *domain_dev)
 	struct asd_sas_phy *sas_phy;
 	struct isci_remote_device *isci_device;
 	enum sci_status status;
-	DECLARE_COMPLETION_ONSTACK(completion);
 
 	isci_host = isci_host_from_sas_ha(domain_dev->port->ha);
 
@@ -525,6 +464,8 @@ int isci_remote_device_found(struct domain_device *domain_dev)
 		return -ENODEV;
 
 	isci_device = isci_remote_device_alloc(isci_host, isci_port);
+	if (!isci_device)
+		return -ENODEV;
 
 	INIT_LIST_HEAD(&isci_device->node);
 	domain_dev->lldd_dev = isci_device;
@@ -533,19 +474,12 @@ int isci_remote_device_found(struct domain_device *domain_dev)
 	isci_remote_device_change_state(isci_device, isci_starting);
 
 
-	spin_lock_irqsave(&isci_port->remote_device_lock, flags);
+	spin_lock_irq(&isci_host->scic_lock);
 	list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
 
-	/* for the device ready event. */
-	isci_device->completion = &completion;
-
+	set_bit(IDEV_START_PENDING, &isci_device->flags);
 	status = isci_remote_device_construct(isci_port, isci_device);
-
-	spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
-
-	/* wait for the device ready callback. */
-	wait_for_completion(isci_device->completion);
-	isci_device->completion = NULL;
+	spin_unlock_irq(&isci_host->scic_lock);
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: isci_device = %p\n",
@@ -553,15 +487,18 @@ int isci_remote_device_found(struct domain_device *domain_dev)
 
 	if (status != SCI_SUCCESS) {
 
-		spin_lock_irqsave(&isci_port->remote_device_lock, flags);
+		spin_lock_irq(&isci_host->scic_lock);
 		isci_remote_device_deconstruct(
 			isci_host,
 			isci_device
 			);
-		spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
+		spin_unlock_irq(&isci_host->scic_lock);
 		return -ENODEV;
 	}
 
+	/* wait for the device ready callback. */
+	wait_for_device_start(isci_host, isci_device);
+
 	return 0;
 }
 /**
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index a208f81..f45a5f0 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -55,25 +55,29 @@
 
 #if !defined(_ISCI_REMOTE_DEVICE_H_)
 #define _ISCI_REMOTE_DEVICE_H_
-#include "scic_user_callback.h"
 
 struct isci_host;
 struct scic_sds_remote_device;
 
 struct isci_remote_device {
-	struct scic_sds_remote_device *sci_device_handle;
 	enum isci_status status;
+	#define IDEV_START_PENDING 0
+	#define IDEV_STOP_PENDING 1
+	#define IDEV_ALLOCATED 2
+	unsigned long flags;
 	struct isci_port *isci_port;
 	struct domain_device *domain_dev;
-	struct completion *completion;
 	struct list_head node;
 	struct list_head reqs_in_process;
-	struct work_struct stop_work;
 	spinlock_t state_lock;
-	spinlock_t host_quiesce_lock;
-	bool host_quiesce;
 };
 
+static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_device *idev)
+{
+	/* core data is an opaque buffer at the end of the idev */
+	return (struct scic_sds_remote_device *) &idev[1];
+}
+
 #define to_isci_remote_device(p)	\
 	container_of(p, struct isci_remote_device, sci_remote_device);
 
@@ -81,22 +85,6 @@ struct isci_remote_device {
 
 
 /**
- * This function gets the status of the remote_device object.
- * @isci_device: This parameter points to the isci_remote_device object
- *
- * status of the object as a isci_status enum.
- */
-static inline
-enum isci_status isci_remote_device_get_state(
-	struct isci_remote_device *isci_device)
-{
-	return (isci_device->host_quiesce)
-	       ? isci_host_quiesce
-	       : isci_device->status;
-}
-
-
-/**
  * isci_dev_from_domain_dev() - This accessor retrieves the remote_device
  *    object reference from the Linux domain_device reference.
  * @domdev,: This parameter points to the Linux domain_device object .
@@ -116,9 +104,8 @@ void isci_remote_device_stop_complete(
 	struct isci_remote_device *,
 	enum sci_status);
 
-enum sci_status isci_remote_device_stop(
-	struct isci_remote_device *isci_device);
-
+enum sci_status isci_remote_device_stop(struct isci_host *ihost,
+					struct isci_remote_device *idev);
 void isci_remote_device_nuke_requests(
 	struct isci_remote_device *isci_device);
 
@@ -142,10 +129,6 @@ bool isci_device_is_reset_pending(
 void isci_device_clear_reset_pending(
 	struct isci_remote_device *isci_device);
 
-void isci_device_set_host_quiesce_lock_state(
-	struct isci_remote_device *isci_device,
-	bool lock_state);
-
 void isci_remote_device_change_state(
 	struct isci_remote_device *isci_device,
 	enum isci_status status);
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 81a7733..0156431 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -179,8 +179,7 @@ static enum sci_status isci_io_request_build(
 	struct smp_discover_response_protocols dev_protocols;
 	enum sci_status status = SCI_SUCCESS;
 	struct sas_task *task = isci_request_access_task(request);
-	struct scic_sds_remote_device *sci_device =
-		isci_device->sci_device_handle;
+	struct scic_sds_remote_device *sci_device = to_sci_dev(isci_device);
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: isci_device = 0x%p; request = %p, "
@@ -408,7 +407,7 @@ int isci_request_execute(
 	unsigned long flags;
 
 	isci_device = isci_dev_from_domain_dev(task->dev);
-	sci_device = isci_device->sci_device_handle;
+	sci_device = to_sci_dev(isci_device);
 
 	/* do common allocation and init of request object. */
 	ret = isci_request_alloc_io(
@@ -464,6 +463,12 @@ int isci_request_execute(
 				 */
 				status = SCI_SUCCESS;
 			}
+			else
+				/* Save the tag for possible task mgmt later. */
+				request->io_tag = scic_io_request_get_io_tag(
+						     request->sci_request_handle);
+
+
 		} else
 			dev_warn(&isci_host->pdev->dev,
 				 "%s: failed request start\n",
@@ -791,9 +796,9 @@ static void isci_task_save_for_upper_layer_completion(
 {
 	struct sas_task *task = isci_request_access_task(request);
 
-	isci_task_set_completion_status(task, response, status,
-					 task_notification_selection);
-
+	task_notification_selection
+		= isci_task_set_completion_status(task, response, status,
+						  task_notification_selection);
 
 	/* Tasks aborted specifically by a call to the lldd_abort_task
 	 * function should not be completed to the host in the regular path.
@@ -804,53 +809,68 @@ static void isci_task_save_for_upper_layer_completion(
 
 		/* Normal notification (task_done) */
 		dev_dbg(&host->pdev->dev,
-			"%s: Normal - task = %p, response=%d, status=%d\n",
+			"%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n",
 			__func__,
 			task,
-			response,
-			status);
+			task->task_status.resp, response,
+			task->task_status.stat, status);
 		/* Add to the completed list. */
 		list_add(&request->completed_node,
 			 &host->requests_to_complete);
+
+		/* Take the request off the device's pending request list. */
+		list_del_init(&request->dev_node);
 		break;
 
 	case isci_perform_aborted_io_completion:
-		/*
-		 * No notification because this request is already
-		 * in the abort path.
+		/* No notification to libsas because this request is
+		 * already in the abort path.
 		 */
 		dev_warn(&host->pdev->dev,
-			 "%s: Aborted - task = %p, response=%d, status=%d\n",
+			 "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n",
 			 __func__,
 			 task,
-			 response,
-			 status);
+			 task->task_status.resp, response,
+			 task->task_status.stat, status);
+
+		/* Wake up whatever process was waiting for this
+		 * request to complete.
+		 */
+		WARN_ON(request->io_request_completion == NULL);
+
+		if (request->io_request_completion != NULL) {
+
+			/* Signal whoever is waiting that this
+			* request is complete.
+			*/
+			complete(request->io_request_completion);
+		}
 		break;
 
 	case isci_perform_error_io_completion:
 		/* Use sas_task_abort */
 		dev_warn(&host->pdev->dev,
-			 "%s: Error - task = %p, response=%d, status=%d\n",
+			 "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n",
 			 __func__,
 			 task,
-			 response,
-			 status);
+			 task->task_status.resp, response,
+			 task->task_status.stat, status);
 		/* Add to the aborted list. */
 		list_add(&request->completed_node,
-			 &host->requests_to_abort);
+			 &host->requests_to_errorback);
 		break;
 
 	default:
 		dev_warn(&host->pdev->dev,
-			 "%s: Unknown - task = %p, response=%d, status=%d\n",
+			 "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n",
 			 __func__,
 			 task,
-			 response,
-			 status);
+			 task->task_status.resp, response,
+			 task->task_status.stat, status);
 
-		/* Add to the aborted list. */
+		/* Add to the error to libsas list. */
 		list_add(&request->completed_node,
-			 &host->requests_to_abort);
+			 &host->requests_to_errorback);
 		break;
 	}
 }
@@ -874,8 +894,6 @@ void isci_request_io_request_complete(
 	struct ssp_response_iu *resp_iu;
 	void *resp_buf;
 	unsigned long task_flags;
-	unsigned long state_flags;
-	struct completion *io_request_completion;
 	struct isci_remote_device *isci_device   = request->isci_device;
 	enum service_response response       = SAS_TASK_UNDELIVERED;
 	enum exec_status status         = SAS_ABORTED_TASK;
@@ -892,9 +910,8 @@ void isci_request_io_request_complete(
 		task->data_dir,
 		completion_status);
 
-	spin_lock_irqsave(&request->state_lock, state_flags);
+	spin_lock(&request->state_lock);
 	request_status = isci_request_get_state(request);
-	spin_unlock_irqrestore(&request->state_lock, state_flags);
 
 	/* Decode the request status.  Note that if the request has been
 	 * aborted by a task management function, we don't care
@@ -929,6 +946,8 @@ void isci_request_io_request_complete(
 
 		complete_to_host = isci_perform_aborted_io_completion;
 		/* This was an aborted request. */
+
+		spin_unlock(&request->state_lock);
 		break;
 
 	case aborting:
@@ -956,6 +975,8 @@ void isci_request_io_request_complete(
 		complete_to_host = isci_perform_aborted_io_completion;
 
 		/* This was an aborted request. */
+
+		spin_unlock(&request->state_lock);
 		break;
 
 	case terminating:
@@ -978,13 +999,20 @@ void isci_request_io_request_complete(
 		else
 			status = SAS_ABORTED_TASK;
 
-		complete_to_host = isci_perform_normal_io_completion;
+		complete_to_host = isci_perform_aborted_io_completion;
 
 		/* This was a terminated request. */
+
+		spin_unlock(&request->state_lock);
 		break;
 
 	default:
 
+		/* The request is done from an SCU HW perspective. */
+		request->status = completed;
+
+		spin_unlock(&request->state_lock);
+
 		/* This is an active request being completed from the core. */
 		switch (completion_status) {
 
@@ -1137,6 +1165,10 @@ void isci_request_io_request_complete(
 			task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
 			spin_unlock_irqrestore(&task->task_state_lock, task_flags);
 
+			/* Fail the I/O. */
+			response = SAS_TASK_UNDELIVERED;
+			status = SAM_STAT_TASK_ABORTED;
+
 			complete_to_host = isci_perform_error_io_completion;
 			request->complete_in_target = false;
 			break;
@@ -1177,7 +1209,7 @@ void isci_request_io_request_complete(
 	/* complete the io request to the core. */
 	scic_controller_complete_io(
 		isci_host->core_controller,
-		isci_device->sci_device_handle,
+		to_sci_dev(isci_device),
 		request->sci_request_handle
 		);
 	/* NULL the request handle so it cannot be completed or
@@ -1186,28 +1218,6 @@ void isci_request_io_request_complete(
 	 */
 	request->sci_request_handle = NULL;
 
-	/* Only remove the request from the remote device list
-	 * of pending requests if we have not requested error
-	 * handling on this request.
-	 */
-	if (complete_to_host != isci_perform_error_io_completion)
-		list_del_init(&request->dev_node);
-
-
-	/* Save possible completion ptr. */
-	io_request_completion = request->io_request_completion;
-
-	if (io_request_completion) {
-
-		/* This is inherantly a regular I/O request,
-		 * since we are currently in the regular
-		 * I/O completion callback function.
-		 * Signal whoever is waiting that this
-		 * request is complete.
-		 */
-		complete(io_request_completion);
-	}
-
 	isci_host_can_dequeue(isci_host, 1);
 }
 
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 166295e..b45c0f1 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -71,7 +71,8 @@ enum isci_request_status {
 	completed   = 0x03,
 	aborting    = 0x04,
 	aborted     = 0x05,
-	terminating = 0x06
+	terminating = 0x06,
+	dead        = 0x07
 };
 
 enum task_type {
diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c
index 19b0eea..7a1b586 100644
--- a/drivers/scsi/isci/sata.c
+++ b/drivers/scsi/isci/sata.c
@@ -324,7 +324,7 @@ int isci_task_send_lu_reset_sata(
 
 	/* Leave SRST high for a bit. */
 	#define ISCI_SRST_ASSERT_DELAY 100 /* usecs */
-	scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY);
+	udelay(ISCI_SRST_ASSERT_DELAY);
 
 	/* Deassert SRST. */
 	isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low,
@@ -348,7 +348,7 @@ int isci_task_send_lu_reset_sata(
 	spin_lock_irqsave(&isci_host->scic_lock, flags);
 
 	/* Resume the device. */
-	scic_sds_remote_device_resume(isci_device->sci_device_handle);
+	scic_sds_remote_device_resume(to_sci_dev(isci_device));
 
 	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 6f98f6c..d00b4c9 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -54,6 +54,8 @@
  */
 
 #include <linux/completion.h>
+#include <linux/irqflags.h>
+#include <scsi/sas_ata.h>
 #include "scic_task_request.h"
 #include "scic_remote_device.h"
 #include "scic_io_request.h"
@@ -64,6 +66,91 @@
 #include "sata.h"
 #include "task.h"
 
+/**
+* isci_task_complete_for_upper_layer() - This function completes the request
+*    to the upper layer driver in the case where an I/O needs to be completed
+*    back in the submit path.
+* @host: This parameter is a pointer to the host on which the the request
+*    should be queued (either as an error or success).
+* @task: This parameter is the completed request.
+* @response: This parameter is the response code for the completed task.
+* @status: This parameter is the status code for the completed task.
+*
+* none.
+*/
+static void isci_task_complete_for_upper_layer(struct sas_task *task,
+					       enum service_response response,
+					       enum exec_status status,
+					       enum isci_completion_selection task_notification_selection)
+{
+	unsigned long    flags = 0;
+	struct Scsi_Host *host = NULL;
+
+	task_notification_selection
+		= isci_task_set_completion_status(task, response, status,
+						  task_notification_selection);
+
+	/* Tasks aborted specifically by a call to the lldd_abort_task
+	* function should not be completed to the host in the regular path.
+	*/
+	switch (task_notification_selection) {
+		case isci_perform_normal_io_completion:
+			/* Normal notification (task_done) */
+			dev_dbg(task->dev->port->ha->dev,
+				"%s: Normal - task = %p, response=%d, status=%d\n",
+				__func__, task, response, status);
+
+			if (dev_is_sata(task->dev)) {
+				/* Since we are still in the submit path, and since
+				* libsas takes the host lock on behalf of SATA
+				* devices before I/O starts, we need to unlock
+				* before we can call back and report the I/O
+				* submission error.
+				*/
+				if (task->dev
+				    && task->dev->port
+				    && task->dev->port->ha) {
+
+					host = task->dev->port->ha->core.shost;
+					raw_local_irq_save(flags);
+					spin_unlock(host->host_lock);
+				}
+				task->task_done(task);
+				if (host) {
+					spin_lock(host->host_lock);
+					raw_local_irq_restore(flags);
+				}
+			} else
+				task->task_done(task);
+
+			task->lldd_task = NULL;
+			break;
+
+		case isci_perform_aborted_io_completion:
+			/* No notification because this request is already in the
+			* abort path.
+			*/
+			dev_warn(task->dev->port->ha->dev,
+				 "%s: Aborted - task = %p, response=%d, status=%d\n",
+				 __func__, task, response, status);
+			break;
+
+		case isci_perform_error_io_completion:
+			/* Use sas_task_abort */
+			dev_warn(task->dev->port->ha->dev,
+				 "%s: Error - task = %p, response=%d, status=%d\n",
+				 __func__, task, response, status);
+			sas_task_abort(task);
+			break;
+
+		default:
+			dev_warn(task->dev->port->ha->dev,
+				 "%s: isci task notification default case!",
+				 __func__);
+			sas_task_abort(task);
+			break;
+	}
+}
 
 /**
  * isci_task_execute_task() - This function is one of the SAS Domain Template
@@ -81,24 +168,12 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
 	struct isci_request *request = NULL;
 	struct isci_remote_device *device;
 	unsigned long flags;
-	unsigned long quiesce_flags = 0;
 	int ret;
 	enum sci_status status;
-
+	enum isci_status device_status;
 
 	dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num);
 
-	if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
-
-		isci_task_complete_for_upper_layer(
-			task,
-			SAS_TASK_UNDELIVERED,
-			SAM_STAT_TASK_ABORTED,
-			isci_perform_normal_io_completion
-			);
-
-		return 0;  /* The I/O was accepted (and failed). */
-	}
 	if ((task->dev == NULL) || (task->dev->port == NULL)) {
 
 		/* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer
@@ -144,114 +219,105 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
 			/* We don't have a valid host reference, so we
 			 * can't control the host queueing condition.
 			 */
-			continue;
+			goto next_task;
 		}
 
 		device = isci_dev_from_domain_dev(task->dev);
 
 		isci_host = isci_host_from_sas_ha(task->dev->port->ha);
 
-		/* check if the controller hasn't started or if the device
-		 * is ready but not accepting IO.
-		 */
-		if (device) {
+		if (device)
+			device_status = device->status;
+		else
+			device_status = isci_freed;
 
-			spin_lock_irqsave(&device->host_quiesce_lock,
-					  quiesce_flags);
-		}
 		/* From this point onward, any process that needs to guarantee
 		 * that there is no kernel I/O being started will have to wait
 		 * for the quiesce spinlock.
 		 */
 
-		if ((device && ((isci_remote_device_get_state(device) == isci_ready) ||
-		    (isci_remote_device_get_state(device) == isci_host_quiesce)))) {
+		if (device_status != isci_ready_for_io) {
 
 			/* Forces a retry from scsi mid layer. */
 			dev_warn(task->dev->port->ha->dev,
 				 "%s: task %p: isci_host->status = %d, "
-				 "device = %p\n",
+				 "device = %p; device_status = 0x%x\n\n",
 				 __func__,
 				 task,
 				 isci_host_get_state(isci_host),
-				 device);
-
-			if (device)
-				dev_dbg(task->dev->port->ha->dev,
-					"%s: device->status = 0x%x\n",
-					__func__,
-					isci_remote_device_get_state(device));
+				 device, device_status);
 
-			/* Indicate QUEUE_FULL so that the scsi midlayer
-			 * retries.
-			 */
-			isci_task_complete_for_upper_layer(
-				task,
-				SAS_TASK_COMPLETE,
-				SAS_QUEUE_FULL,
-				isci_perform_normal_io_completion
-				);
+			if (device_status == isci_ready) {
+				/* Indicate QUEUE_FULL so that the scsi midlayer
+				* retries.
+				*/
+				isci_task_complete_for_upper_layer(
+					task,
+					SAS_TASK_COMPLETE,
+					SAS_QUEUE_FULL,
+					isci_perform_normal_io_completion
+					);
+			} else {
+				/* Else, the device is going down. */
+				isci_task_complete_for_upper_layer(
+					task,
+					SAS_TASK_UNDELIVERED,
+					SAS_DEVICE_UNKNOWN,
+					isci_perform_normal_io_completion
+					);
+			}
 			isci_host_can_dequeue(isci_host, 1);
-		}
-		/* the device is going down... */
-		else if (!device || (isci_ready_for_io != isci_remote_device_get_state(device))) {
+		} else {
+			/* There is a device and it's ready for I/O. */
+			spin_lock_irqsave(&task->task_state_lock, flags);
 
-			dev_dbg(task->dev->port->ha->dev,
-				"%s: task %p: isci_host->status = %d, "
-				"device = %p\n",
-				__func__,
-				task,
-				isci_host_get_state(isci_host),
-				device);
+			if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
 
-			if (device)
-				dev_dbg(task->dev->port->ha->dev,
-					"%s: device->status = 0x%x\n",
-					__func__,
-					isci_remote_device_get_state(device));
+				spin_unlock_irqrestore(&task->task_state_lock,
+						       flags);
 
-			/* Indicate SAS_TASK_UNDELIVERED, so that the scsi
-			 * midlayer removes the target.
-			 */
-			isci_task_complete_for_upper_layer(
-				task,
-				SAS_TASK_UNDELIVERED,
-				SAS_DEVICE_UNKNOWN,
-				isci_perform_normal_io_completion
-				);
-			isci_host_can_dequeue(isci_host, 1);
+				isci_task_complete_for_upper_layer(
+					task,
+					SAS_TASK_UNDELIVERED,
+					SAM_STAT_TASK_ABORTED,
+					isci_perform_normal_io_completion
+					);
 
-		} else {
-			/* build and send the request. */
-			status = isci_request_execute(isci_host, task, &request,
-						      gfp_flags);
+				/* The I/O was aborted. */
 
-			if (status == SCI_SUCCESS) {
-				spin_lock_irqsave(&task->task_state_lock, flags);
+			} else {
 				task->task_state_flags |= SAS_TASK_AT_INITIATOR;
 				spin_unlock_irqrestore(&task->task_state_lock, flags);
-			} else {
-				/* Indicate QUEUE_FULL so that the scsi
-				 * midlayer retries. if the request
-				 * failed for remote device reasons,
-				 * it gets returned as
-				 * SAS_TASK_UNDELIVERED next time
-				 * through.
-				 */
-				isci_task_complete_for_upper_layer(
+
+				/* build and send the request. */
+				status = isci_request_execute(isci_host, task, &request,
+							      gfp_flags);
+
+				if (status != SCI_SUCCESS) {
+
+					spin_lock_irqsave(&task->task_state_lock, flags);
+					/* Did not really start this command. */
+					task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+					spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+					/* Indicate QUEUE_FULL so that the scsi
+					* midlayer retries. if the request
+					* failed for remote device reasons,
+					* it gets returned as
+					* SAS_TASK_UNDELIVERED next time
+					* through.
+					*/
+					isci_task_complete_for_upper_layer(
 						task,
 						SAS_TASK_COMPLETE,
 						SAS_QUEUE_FULL,
 						isci_perform_normal_io_completion
 						);
-				isci_host_can_dequeue(isci_host, 1);
+					isci_host_can_dequeue(isci_host, 1);
+				}
 			}
 		}
-		if (device) {
-			spin_unlock_irqrestore(&device->host_quiesce_lock,
-					       quiesce_flags
-					       );
-		}
+next_task:
 		task = list_entry(task->list.next, struct sas_task, list);
 	} while (--num > 0);
 	return 0;
@@ -285,7 +351,7 @@ static enum sci_status isci_task_request_build(
 		"%s: isci_tmf = %p\n", __func__, isci_tmf);
 
 	isci_device = isci_tmf->device;
-	sci_device = isci_device->sci_device_handle;
+	sci_device = to_sci_dev(isci_device);
 
 	/* do common allocation and init of request object. */
 	status = isci_request_alloc_tmf(
@@ -395,7 +461,7 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg)
 		/* Terminate the TMF transmit request. */
 		status = scic_controller_terminate_request(
 			request->isci_host->core_controller,
-			request->isci_device->sci_device_handle,
+			to_sci_dev(request->isci_device),
 			request->sci_request_handle
 			);
 
@@ -442,21 +508,18 @@ int isci_task_execute_tmf(
 	/* sanity check, return TMF_RESP_FUNC_FAILED
 	 * if the device is not there and ready.
 	 */
-	if (!isci_device ||
-	    ((isci_ready_for_io != isci_remote_device_get_state(isci_device)) &&
-	    (isci_host_quiesce != isci_remote_device_get_state(isci_device)))) {
+	if (!isci_device || isci_device->status != isci_ready_for_io) {
 		dev_dbg(&isci_host->pdev->dev,
 			"%s: isci_device = %p not ready (%d)\n",
 			__func__,
-			isci_device,
-			isci_remote_device_get_state(isci_device));
+			isci_device, isci_device->status);
 		return TMF_RESP_FUNC_FAILED;
 	} else
 		dev_dbg(&isci_host->pdev->dev,
 			"%s: isci_device = %p\n",
 			__func__, isci_device);
 
-	sci_device = isci_device->sci_device_handle;
+	sci_device = to_sci_dev(isci_device);
 
 	/* Assign the pointer to the TMF's completion kernel wait structure. */
 	tmf->complete = &completion;
@@ -475,14 +538,8 @@ int isci_task_execute_tmf(
 	}
 
 	/* Allocate the TMF timeout timer. */
-	tmf->timeout_timer = isci_timer_create(
-		&isci_host->timer_list_struct,
-		isci_host,
-		request,
-		isci_tmf_timeout_cb
-		);
-
 	spin_lock_irqsave(&isci_host->scic_lock, flags);
+	tmf->timeout_timer = isci_timer_create(isci_host, request, isci_tmf_timeout_cb);
 
 	/* Start the timer. */
 	if (tmf->timeout_timer)
@@ -557,9 +614,7 @@ int isci_task_execute_tmf(
 
 	/* Clean up the timer if needed. */
 	if (tmf->timeout_timer) {
-		isci_timer_stop(tmf->timeout_timer);
-		isci_timer_free(&isci_host->timer_list_struct,
-				tmf->timeout_timer);
+		isci_del_timer(isci_host, tmf->timeout_timer);
 		tmf->timeout_timer = NULL;
 	}
 
@@ -591,6 +646,20 @@ void isci_task_build_tmf(
 	tmf->cb_data       = cb_data;
 }
 
+void isci_task_build_abort_task_tmf(
+	struct isci_tmf *tmf,
+	struct isci_remote_device *isci_device,
+	enum isci_tmf_function_codes code,
+	void (*tmf_sent_cb)(enum isci_tmf_cb_state,
+			    struct isci_tmf *,
+			    void *),
+	struct isci_request *old_request)
+{
+	isci_task_build_tmf(tmf, isci_device, code, tmf_sent_cb,
+			    (void *)old_request);
+	tmf->io_tag = old_request->io_tag;
+}
+
 static struct isci_request *isci_task_get_request_from_task(
 	struct sas_task *task,
 	struct isci_host **isci_host,
@@ -651,9 +720,6 @@ static enum isci_request_status isci_task_validate_request_to_abort(
 		old_state = isci_request_change_started_to_aborted(
 			isci_request, aborted_io_completion);
 
-		/* Only abort requests in the started state. */
-		if (old_state != started)
-			old_state = unallocated;
 	}
 
 	return old_state;
@@ -664,22 +730,91 @@ static void isci_request_cleanup_completed_loiterer(
 	struct isci_remote_device *isci_device,
 	struct isci_request *isci_request)
 {
-	struct sas_task *task = isci_request_access_task(isci_request);
-	unsigned long flags;
+	struct sas_task     *task;
+	unsigned long       flags;
+
+	task = (isci_request->ttype == io_task)
+		? isci_request_access_task(isci_request)
+		: NULL;
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: isci_device=%p, request=%p, task=%p\n",
-		__func__, isci_device, isci_request,
-		isci_request->ttype_ptr.io_task_ptr);
+		__func__, isci_device, isci_request, task);
 
 	spin_lock_irqsave(&isci_host->scic_lock, flags);
 	list_del_init(&isci_request->dev_node);
-	if (task != NULL)
-		task->lldd_task = NULL;
 	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
+	if (task != NULL) {
+
+		spin_lock_irqsave(&task->task_state_lock, flags);
+		task->lldd_task = NULL;
+
+		isci_set_task_doneflags(task);
+
+		/* If this task is not in the abort path, call task_done. */
+		if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+
+			spin_unlock_irqrestore(&task->task_state_lock, flags);
+			task->task_done(task);
+		} else
+			spin_unlock_irqrestore(&task->task_state_lock, flags);
+	}
 	isci_request_free(isci_host, isci_request);
 }
+
+/**
+* @isci_termination_timed_out(): this function will deal with a request for
+* which the wait for termination has timed-out.
+*
+* @isci_host    This SCU.
+* @isci_request The I/O request being terminated.
+*/
+static void
+isci_termination_timed_out(
+	struct isci_host    * host,
+	struct isci_request * request
+	)
+{
+	unsigned long state_flags;
+
+	dev_warn(&host->pdev->dev,
+		"%s: host = %p; request = %p\n",
+		__func__, host, request);
+
+	/* At this point, the request to terminate
+	* has timed out. The best we can do is to
+	* have the request die a silent death
+	* if it ever completes.
+	*/
+	spin_lock_irqsave(&request->state_lock, state_flags);
+
+	if (request->status == started) {
+
+		/* Set the request state to "dead",
+		* and clear the task pointer so that an actual
+		* completion event callback doesn't do
+		* anything.
+		*/
+		request->status = dead;
+
+		/* Clear the timeout completion event pointer.*/
+		request->io_request_completion = NULL;
+
+		if (request->ttype == io_task) {
+
+			/* Break links with the sas_task. */
+			if (request->ttype_ptr.io_task_ptr != NULL) {
+
+				request->ttype_ptr.io_task_ptr->lldd_task = NULL;
+				request->ttype_ptr.io_task_ptr            = NULL;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&request->state_lock, state_flags);
+}
+
+
 /**
  * isci_terminate_request_core() - This function will terminate the given
  *    request, and wait for it to complete.  This function must only be called
@@ -694,49 +829,37 @@ static void isci_request_cleanup_completed_loiterer(
 static void isci_terminate_request_core(
 	struct isci_host *isci_host,
 	struct isci_remote_device *isci_device,
-	struct isci_request *isci_request,
-	struct completion *request_completion)
+	struct isci_request *isci_request)
 {
-	enum sci_status status                 = SCI_SUCCESS;
+	enum sci_status status      = SCI_SUCCESS;
 	bool was_terminated         = false;
 	bool needs_cleanup_handling = false;
 	enum isci_request_status request_status;
 	unsigned long flags;
+	unsigned long timeout_remaining;
+
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: device = %p; request = %p\n",
 		__func__, isci_device, isci_request);
 
-	/* Peek at the current status of the request.  This will tell
-	 * us if there was special handling on the request such that it
-	 * needs to be detached and freed here.
-	 */
-	spin_lock_irqsave(&isci_request->state_lock, flags);
-	request_status = isci_request_get_state(isci_request);
-
-	/* TMFs are in their own thread */
-	if ((isci_request->ttype == io_task) &&
-	    ((request_status == aborted) ||
-	     (request_status == aborting) ||
-	     (request_status == terminating)))
-		/* The completion routine won't free a request in
-		 * the aborted/aborting/terminating state, so we do
-		 * it here.
-		 */
-		needs_cleanup_handling = true;
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
 
-	spin_unlock_irqrestore(&isci_request->state_lock, flags);
+	/* Note that we are not going to control
+	* the target to abort the request.
+	*/
+	isci_request->complete_in_target = true;
 
-	spin_lock_irqsave(&isci_host->scic_lock, flags);
 	/* Make sure the request wasn't just sitting around signalling
 	 * device condition (if the request handle is NULL, then the
 	 * request completed but needed additional handling here).
 	 */
 	if (isci_request->sci_request_handle != NULL) {
 		was_terminated = true;
+		needs_cleanup_handling = true;
 		status = scic_controller_terminate_request(
 			isci_host->core_controller,
-			isci_device->sci_device_handle,
+			to_sci_dev(isci_device),
 			isci_request->sci_request_handle
 			);
 	}
@@ -747,27 +870,73 @@ static void isci_terminate_request_core(
 	 * fail is when the io request is completed and
 	 * being aborted.
 	 */
-	if (status != SCI_SUCCESS)
+	if (status != SCI_SUCCESS) {
 		dev_err(&isci_host->pdev->dev,
 			"%s: scic_controller_terminate_request"
 			" returned = 0x%x\n",
 			__func__,
 			status);
-	else {
+		/* Clear the completion pointer from the request. */
+		isci_request->io_request_completion = NULL;
+
+	} else {
 		if (was_terminated) {
 			dev_dbg(&isci_host->pdev->dev,
 				"%s: before completion wait (%p)\n",
 				__func__,
-				request_completion);
+				isci_request->io_request_completion);
 
 			/* Wait here for the request to complete. */
-			wait_for_completion(request_completion);
+			#define TERMINATION_TIMEOUT_MSEC 50
+			timeout_remaining
+				= wait_for_completion_timeout(
+				   isci_request->io_request_completion,
+				   msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
 
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: after completion wait (%p)\n",
-				__func__,
-				request_completion);
+			if (!timeout_remaining) {
+
+				isci_termination_timed_out(isci_host,
+							   isci_request);
+
+				dev_err(&isci_host->pdev->dev,
+					"%s: *** Timeout waiting for "
+					"termination(%p/%p)\n",
+					__func__,
+					isci_request->io_request_completion,
+					isci_request);
+
+			} else
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: after completion wait (%p)\n",
+					__func__,
+					isci_request->io_request_completion);
+		}
+		/* Clear the completion pointer from the request. */
+		isci_request->io_request_completion = NULL;
+
+		/* Peek at the status of the request.  This will tell
+		* us if there was special handling on the request such that it
+		* needs to be detached and freed here.
+		*/
+		spin_lock_irqsave(&isci_request->state_lock, flags);
+		request_status = isci_request_get_state(isci_request);
+
+		if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
+		    && ((request_status == aborted)
+			|| (request_status == aborting)
+			|| (request_status == terminating)
+			|| (request_status == completed)
+			|| (request_status == dead)
+			)
+		    ) {
+
+			/* The completion routine won't free a request in
+			* the aborted/aborting/etc. states, so we do
+			* it here.
+			*/
+			needs_cleanup_handling = true;
 		}
+		spin_unlock_irqrestore(&isci_request->state_lock, flags);
 
 		if (needs_cleanup_handling)
 			isci_request_cleanup_completed_loiterer(
@@ -775,6 +944,7 @@ static void isci_terminate_request_core(
 				);
 	}
 }
+
 static void isci_terminate_request(
 	struct isci_host *isci_host,
 	struct isci_remote_device *isci_device,
@@ -782,11 +952,7 @@ static void isci_terminate_request(
 	enum isci_request_status new_request_state)
 {
 	enum isci_request_status old_state;
-
 	DECLARE_COMPLETION_ONSTACK(request_completion);
-	unsigned long flags;
-
-	spin_lock_irqsave(&isci_host->scic_lock, flags);
 
 	/* Change state to "new_request_state" if it is currently "started" */
 	old_state = isci_request_change_started_to_newstate(
@@ -795,10 +961,10 @@ static void isci_terminate_request(
 		new_request_state
 		);
 
-	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+	if ((old_state == started) || (old_state == completed)) {
 
-	if (old_state == started)
-		/* This request was not already being aborted. If it had been,
+		/* If the old_state is started:
+		 * This request was not already being aborted. If it had been,
 		 * then the aborting I/O (ie. the TMF request) would not be in
 		 * the aborting state, and thus would be terminated here.  Note
 		 * that since the TMF completion's call to the kernel function
@@ -807,9 +973,15 @@ static void isci_terminate_request(
 		 * special wait here for already aborting requests - the
 		 * termination of the TMF request will force the request
 		 * to finish it's already started terminate.
+		 *
+		 * If old_state == completed:
+		 * This request completed from the SCU hardware perspective
+		 * and now just needs cleaning up in terms of freeing the
+		 * request and potentially calling up to libsas.
 		 */
 		isci_terminate_request_core(isci_host, isci_device,
-					    isci_request, &request_completion);
+					    isci_request);
+	}
 }
 
 /**
@@ -828,77 +1000,44 @@ void isci_terminate_pending_requests(
 	struct isci_remote_device *isci_device,
 	enum isci_request_status new_request_state)
 {
-	struct isci_request *isci_request;
-	struct sas_task *task;
-	bool done = false;
-	unsigned long flags;
+	struct isci_request *request;
+	struct isci_request *next_request;
+	unsigned long       flags;
+	struct list_head    aborted_request_list;
+
+	INIT_LIST_HEAD(&aborted_request_list);
 
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: isci_device = %p (new request state = %d)\n",
 		__func__, isci_device, new_request_state);
 
-	#define ISCI_TERMINATE_SHOW_PENDING_REQUESTS
-	#ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS
-	{
-		struct isci_request *request;
-
-		/* Only abort the task if it's in the
-		 * device's request_in_process list
-		 */
-		list_for_each_entry(request,
-				    &isci_device->reqs_in_process,
-				    dev_node)
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: isci_device = %p; request is on "
-				"reqs_in_process list: %p\n",
-				__func__, isci_device, request);
-	}
-	#endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */
-
-	/* Clean up all pending requests. */
-	do {
-		spin_lock_irqsave(&isci_host->scic_lock, flags);
-
-		if (list_empty(&isci_device->reqs_in_process)) {
-
-			done = true;
-			spin_unlock_irqrestore(&isci_host->scic_lock, flags);
-
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: isci_device = %p; done.\n",
-				__func__, isci_device);
-		} else {
-			/* The list was not empty - grab the first request. */
-			isci_request = list_first_entry(
-				&isci_device->reqs_in_process,
-				struct isci_request, dev_node
-				);
-			/* Note that we are not expecting to have to control
-			 * the target to abort the request.
-			 */
-			isci_request->complete_in_target = true;
-
-			spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
 
-			/* Get the libsas task reference. */
-			task = isci_request_access_task(isci_request);
+	/* Move all of the pending requests off of the device list. */
+	list_splice_init(&isci_device->reqs_in_process,
+			 &aborted_request_list);
 
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: isci_device=%p request=%p; task=%p\n",
-				__func__, isci_device, isci_request, task);
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
-			/* Mark all still pending I/O with the selected next
-			 * state.
-			 */
-			isci_terminate_request(isci_host, isci_device,
-					       isci_request, new_request_state
-					       );
+	/* Iterate through the now-local list. */
+	list_for_each_entry_safe(request, next_request,
+				 &aborted_request_list, dev_node) {
 
-			/* Set the 'done' state on the task. */
-			if (task)
-				isci_task_all_done(task);
-		}
-	} while (!done);
+		dev_warn(&isci_host->pdev->dev,
+			"%s: isci_device=%p request=%p; task=%p\n",
+			__func__,
+			isci_device, request,
+			((request->ttype == io_task)
+				? isci_request_access_task(request)
+				: NULL));
+
+		/* Mark all still pending I/O with the selected next
+		* state, terminate and free it.
+		*/
+		isci_terminate_request(isci_host, isci_device,
+				       request, new_request_state
+				       );
+	}
 }
 
 /**
@@ -994,9 +1133,6 @@ int isci_task_lu_reset(
 		return TMF_RESP_FUNC_FAILED;
 	}
 
-	/* Stop I/O to the remote device. */
-	isci_device_set_host_quiesce_lock_state(isci_device, true);
-
 	/* Send the task management part of the reset. */
 	if (sas_protocol_ata(domain_device->tproto)) {
 		ret = isci_task_send_lu_reset_sata(
@@ -1012,9 +1148,6 @@ int isci_task_lu_reset(
 						isci_device,
 						terminating);
 
-	/* Resume I/O to the remote device. */
-	isci_device_set_host_quiesce_lock_state(isci_device, false);
-
 	return ret;
 }
 
@@ -1070,7 +1203,8 @@ static void isci_abort_task_process_cb(
 		 * request state was already set to "aborted" by the abort
 		 * task function.
 		 */
-		BUG_ON(old_request->status != aborted);
+		BUG_ON((old_request->status != aborted)
+			&& (old_request->status != completed));
 		break;
 
 	case isci_tmf_timed_out:
@@ -1103,13 +1237,15 @@ static void isci_abort_task_process_cb(
 int isci_task_abort_task(struct sas_task *task)
 {
 	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
-	struct isci_request *old_request = NULL;
+	struct isci_request       *old_request = NULL;
+	enum isci_request_status  old_state;
 	struct isci_remote_device *isci_device = NULL;
-	struct isci_host *isci_host = NULL;
-	struct isci_tmf tmf;
-	int ret = TMF_RESP_FUNC_FAILED;
-	unsigned long flags;
-	bool any_dev_reset, device_stopping;
+	struct isci_host          *isci_host = NULL;
+	struct isci_tmf           tmf;
+	int                       ret = TMF_RESP_FUNC_FAILED;
+	unsigned long             flags;
+	bool                      any_dev_reset = false;
+	bool                      device_stopping;
 
 	/* Get the isci_request reference from the task.  Note that
 	 * this check does not depend on the pending request list
@@ -1129,21 +1265,6 @@ int isci_task_abort_task(struct sas_task *task)
 	device_stopping = (isci_device->status == isci_stopping)
 			  || (isci_device->status == isci_stopped);
 
-#ifdef NOMORE
-	/* This abort task function is the first stop of the libsas error
-	 * handler thread. Since libsas is executing in a thread with a
-	 * referernce to the "task" parameter, that task cannot be completed
-	 * directly back to the upper layers.  In order to make sure that
-	 * the task is managed correctly if this abort task fails, set the
-	 * "SAS_TASK_STATE_ABORTED" bit now such that completions up the
-	 * stack will be intercepted and only allowed to happen in the
-	 * libsas SCSI error handler thread.
-	 */
-	spin_lock_irqsave(&task->task_state_lock, flags);
-	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
-	spin_unlock_irqrestore(&task->task_state_lock, flags);
-#endif  /* NOMORE */
-
 	/* This version of the driver will fail abort requests for
 	 * SATA/STP.  Failing the abort request this way will cause the
 	 * SCSI error handler thread to escalate to LUN reset
@@ -1159,35 +1280,27 @@ int isci_task_abort_task(struct sas_task *task)
 	dev_dbg(&isci_host->pdev->dev,
 		"%s: old_request == %p\n", __func__, old_request);
 
+	if (!device_stopping)
+		any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device);
+
 	spin_lock_irqsave(&task->task_state_lock, flags);
 
 	/* Don't do resets to stopping devices. */
-	if (device_stopping)
-		task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+	if (device_stopping) {
 
-	/* See if there is a pending device reset for this device. */
-	any_dev_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
-
-	spin_unlock_irqrestore(&task->task_state_lock, flags);
+		task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+		any_dev_reset = false;
 
-	if ((isci_device != NULL) && !device_stopping)
+	} else	/* See if there is a pending device reset for this device. */
 		any_dev_reset = any_dev_reset
-				|| isci_device_is_reset_pending(isci_host,
-								isci_device
-								);
+			|| (task->task_state_flags & SAS_TASK_NEED_DEV_RESET);
 
 	/* If the extraction of the request reference from the task
 	 * failed, then the request has been completed (or if there is a
 	 * pending reset then this abort request function must be failed
 	 * in order to escalate to the target reset).
 	 */
-	if ((old_request == NULL) ||
-	    ((old_request != NULL) &&
-	     (old_request->sci_request_handle == NULL) &&
-	     (old_request->complete_in_target)) ||
-	     any_dev_reset) {
-
-		spin_lock_irqsave(&task->task_state_lock, flags);
+	if ((old_request == NULL) || any_dev_reset) {
 
 		/* If the device reset task flag is set, fail the task
 		 * management request.  Otherwise, the original request
@@ -1200,6 +1313,11 @@ int isci_task_abort_task(struct sas_task *task)
 			 */
 			task->task_state_flags &= ~SAS_TASK_STATE_DONE;
 
+			/* Make the reset happen as soon as possible. */
+			task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+
+			spin_unlock_irqrestore(&task->task_state_lock, flags);
+
 			/* Fail the task management request in order to
 			 * escalate to the target reset.
 			 */
@@ -1212,13 +1330,8 @@ int isci_task_abort_task(struct sas_task *task)
 				"task %p on dev %p\n",
 				__func__, task, isci_device);
 
-		} else {
-			ret = TMF_RESP_FUNC_COMPLETE;
-
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: abort task not needed for %p\n",
-				__func__, task);
 
+		} else {
 			/* The request has already completed and there
 			 * is nothing to do here other than to set the task
 			 * done bit, and indicate that the task abort function
@@ -1226,97 +1339,71 @@ int isci_task_abort_task(struct sas_task *task)
 			 */
 			isci_set_task_doneflags(task);
 
-			/* Set the abort bit to make sure that libsas sticks the
-			 * task in the completed task queue.
-			 */
-/*			task->task_state_flags |= SAS_TASK_STATE_ABORTED; */
+			spin_unlock_irqrestore(&task->task_state_lock, flags);
 
-			/* Check for the situation where the request was
-			 * left around on the device list but the
-			 * request already completed.
-			 */
-			if (old_request && !old_request->sci_request_handle) {
+			ret = TMF_RESP_FUNC_COMPLETE;
 
-				isci_request_cleanup_completed_loiterer(
-					isci_host, isci_device, old_request
-					);
-			}
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: abort task not needed for %p\n",
+				__func__, task);
 		}
-		spin_unlock_irqrestore(&task->task_state_lock, flags);
 
 		return ret;
 	}
+	else
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
 
 	spin_lock_irqsave(&isci_host->scic_lock, flags);
 
-	/* Sanity check the request status, and set the I/O kernel completion
+	/* Check the request status and change to "aborting" if currently
+	 * "starting"; if true then set the I/O kernel completion
 	 * struct that will be triggered when the request completes.
 	 */
-	if (isci_task_validate_request_to_abort(
-		    old_request,
-		    isci_host,
-		    isci_device,
-		    &aborted_io_completion)
-	    == unallocated) {
-		dev_dbg(&isci_host->pdev->dev,
-			"%s: old_request not valid for device = %p\n",
-			__func__,
-			isci_device);
-		old_request = NULL;
-	}
-
-	if (!old_request) {
-
-		/* There is no isci_request attached to the sas_task.
-		 * It must have been completed and detached.
-		 */
-		dev_dbg(&isci_host->pdev->dev,
-			"%s: old_request == NULL\n",
-			__func__);
+	old_state = isci_task_validate_request_to_abort(
+				old_request, isci_host, isci_device,
+				&aborted_io_completion);
+	if ((old_state != started) && (old_state != completed)) {
 
 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
-		/* Set the state on the task. */
-		isci_task_all_done(task);
+		/* The request was already being handled by someone else (because
+		* they got to set the state away from started).
+		*/
+		dev_dbg(&isci_host->pdev->dev,
+			"%s:  device = %p; old_request %p already being aborted\n",
+			__func__,
+			isci_device, old_request);
 
 		return TMF_RESP_FUNC_COMPLETE;
 	}
-	if (task->task_proto == SAS_PROTOCOL_SMP || device_stopping) {
-
-		if (device_stopping)
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: device is stopping, thus no TMF\n",
-				__func__);
-		else
-			dev_dbg(&isci_host->pdev->dev,
-				"%s: request is SMP, thus no TMF\n",
-				__func__);
-
-		old_request->complete_in_target = true;
+	if ((task->task_proto == SAS_PROTOCOL_SMP)
+	    || device_stopping
+	    || old_request->complete_in_target
+	    ) {
 
 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: SMP request (%d)"
+			" or device is stopping (%d)"
+			" or complete_in_target (%d), thus no TMF\n",
+			__func__, (task->task_proto == SAS_PROTOCOL_SMP),
+			device_stopping, old_request->complete_in_target);
+
 		/* Set the state on the task. */
 		isci_task_all_done(task);
 
 		ret = TMF_RESP_FUNC_COMPLETE;
 
 		/* Stopping and SMP devices are not sent a TMF, and are not
-		 * reset, but the outstanding I/O request is terminated here.
-		 *
-		 * Clean up the request on our side, and wait for the aborted
-		 * I/O to complete.
+		 * reset, but the outstanding I/O request is terminated below.
 		 */
-		isci_terminate_request_core(isci_host, isci_device, old_request,
-					    &aborted_io_completion);
 	} else {
 		/* Fill in the tmf stucture */
-		isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort,
-				    isci_abort_task_process_cb, old_request);
-
-		tmf.io_tag = scic_io_request_get_io_tag(
-			old_request->sci_request_handle
-			);
+		isci_task_build_abort_task_tmf(&tmf, isci_device,
+					       isci_tmf_ssp_task_abort,
+					       isci_abort_task_process_cb,
+					       old_request);
 
 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
@@ -1324,23 +1411,22 @@ int isci_task_abort_task(struct sas_task *task)
 		ret = isci_task_execute_tmf(isci_host, &tmf,
 					    ISCI_ABORT_TASK_TIMEOUT_MS);
 
-		if (ret == TMF_RESP_FUNC_COMPLETE) {
-			old_request->complete_in_target = true;
-
-			/* Clean up the request on our side, and wait for the aborted I/O to
-			 * complete.
-			 */
-			isci_terminate_request_core(isci_host, isci_device, old_request,
-						    &aborted_io_completion);
-
-			/* Set the state on the task. */
-			isci_task_all_done(task);
-		} else
+		if (ret != TMF_RESP_FUNC_COMPLETE)
 			dev_err(&isci_host->pdev->dev,
 				"%s: isci_task_send_tmf failed\n",
 				__func__);
 	}
+	if (ret == TMF_RESP_FUNC_COMPLETE) {
+		old_request->complete_in_target = true;
+
+		/* Clean up the request on our side, and wait for the aborted I/O to
+		* complete.
+		*/
+		isci_terminate_request_core(isci_host, isci_device, old_request);
+	}
 
+	/* Make sure we do not leave a reference to aborted_io_completion */
+	old_request->io_request_completion = NULL;
 	return ret;
 }
 
@@ -1468,10 +1554,7 @@ void isci_task_request_complete(
 
 	/* Manage the timer if it is still running. */
 	if (tmf->timeout_timer) {
-
-		isci_timer_stop(tmf->timeout_timer);
-		isci_timer_free(&isci_host->timer_list_struct,
-				tmf->timeout_timer);
+		isci_del_timer(isci_host, tmf->timeout_timer);
 		tmf->timeout_timer = NULL;
 	}
 
@@ -1480,7 +1563,7 @@ void isci_task_request_complete(
 
 	scic_controller_complete_task(
 		isci_host->core_controller,
-		isci_device->sci_device_handle,
+		to_sci_dev(isci_device),
 		request->sci_request_handle
 		);
 	/* NULL the request handle to make sure it cannot be terminated
@@ -1623,7 +1706,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd)
 	if (isci_host != NULL)
 		spin_lock_irqsave(&isci_host->scic_lock, flags);
 
-	status = scic_remote_device_reset(isci_dev->sci_device_handle);
+	status = scic_remote_device_reset(to_sci_dev(isci_dev));
 	if (status != SCI_SUCCESS) {
 
 		if (isci_host != NULL)
@@ -1638,9 +1721,6 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd)
 	if (isci_host != NULL)
 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
-	/* Stop I/O to the remote device. */
-	isci_device_set_host_quiesce_lock_state(isci_dev, true);
-
 	/* Make sure all pending requests are able to be fully terminated. */
 	isci_device_clear_reset_pending(isci_dev);
 
@@ -1665,8 +1745,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd)
 
 	if (isci_host != NULL)
 		spin_lock_irqsave(&isci_host->scic_lock, flags);
-	status
-		= scic_remote_device_reset_complete(isci_dev->sci_device_handle);
+	status = scic_remote_device_reset_complete(to_sci_dev(isci_dev));
 
 	if (isci_host != NULL)
 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
@@ -1683,8 +1762,5 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd)
 		"%s: cmd %p, isci_dev %p complete.\n",
 		__func__, cmd, isci_dev);
 
-	/* Resume I/O to the remote device. */
-	isci_device_set_host_quiesce_lock_state(isci_dev, false);
-
 	return TMF_RESP_FUNC_COMPLETE;
 }
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index ced6a8b..b84bedd 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -221,10 +221,19 @@ void isci_task_build_tmf(
 	struct isci_tmf *tmf,
 	struct isci_remote_device *isci_device,
 	enum isci_tmf_function_codes code,
+	void (*tmf_sent_cb)(enum isci_tmf_cb_state,
+			    struct isci_tmf *,
+			    void *),
+	void *cb_data);
+
+void isci_task_build_abort_task_tmf(
+	struct isci_tmf *tmf,
+	struct isci_remote_device *isci_device,
+	enum isci_tmf_function_codes code,
 	void (*tmf_sent_cb)(
 		enum isci_tmf_cb_state,
 		struct isci_tmf *, void *),
-	void *cb_data);
+	struct isci_request *old_request);
 
 int isci_task_execute_tmf(
 	struct isci_host *isci_host,
@@ -280,9 +289,10 @@ static inline void isci_task_all_done(
  * @response: This parameter is the response code for the completed task.
  * @status: This parameter is the status code for the completed task.
  *
- * none.
- */
-static inline void isci_task_set_completion_status(
+* @return The new notification mode for the request.
+*/
+static inline enum isci_completion_selection
+isci_task_set_completion_status(
 	struct sas_task *task,
 	enum service_response response,
 	enum exec_status status,
@@ -292,77 +302,49 @@ static inline void isci_task_set_completion_status(
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
 
+	/* If a device reset is being indicated, make sure the I/O
+	* is in the error path.
+	*/
+	if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) {
+
+		/* Fail the I/O to make sure it goes into the error path. */
+		response = SAS_TASK_UNDELIVERED;
+		status = SAM_STAT_TASK_ABORTED;
+
+		task_notification_selection = isci_perform_error_io_completion;
+	}
 	task->task_status.resp = response;
 	task->task_status.stat = status;
 
-	/* Don't set DONE (or clear AT_INITIATOR) for any task going into the
-	 * error path, because the EH interprets that as a handled error condition.
-	 * Also don't take action if there is a reset pending.
-	 */
-	if ((task_notification_selection != isci_perform_error_io_completion)
-	    && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
-		isci_set_task_doneflags(task);
+	switch (task_notification_selection) {
+
+		case isci_perform_aborted_io_completion:
+			/* This path can occur with task-managed requests as well as
+			* requests terminated because of LUN or device resets.
+			*/
+			/* Fall through to the normal case... */
+
+		case isci_perform_normal_io_completion:
+			/* Normal notification (task_done) */
+			isci_set_task_doneflags(task);
+			break;
+
+		default:
+			WARN_ON(FALSE);
+			/* Fall through to the error case... */
+
+		case isci_perform_error_io_completion:
+			/* Use sas_task_abort */
+			/* Leave SAS_TASK_STATE_DONE clear
+			*  Leave SAS_TASK_AT_INITIATOR set.
+			*/
+			break;
+	}
 
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
-}
-/**
- * isci_task_complete_for_upper_layer() - This function completes the request
- *    to the upper layer driver.
- * @host: This parameter is a pointer to the host on which the the request
- *    should be queued (either as an error or success).
- * @request: This parameter is the completed request.
- * @response: This parameter is the response code for the completed task.
- * @status: This parameter is the status code for the completed task.
- *
- * none.
- */
-static inline void isci_task_complete_for_upper_layer(
-	struct sas_task *task,
-	enum service_response response,
-	enum exec_status status,
-	enum isci_completion_selection task_notification_selection)
-{
-	isci_task_set_completion_status(task, response, status,
-					 task_notification_selection);
 
+	return task_notification_selection;
 
-	/* Tasks aborted specifically by a call to the lldd_abort_task
-	 * function should not be completed to the host in the regular path.
-	 */
-	switch (task_notification_selection) {
-	case isci_perform_normal_io_completion:
-		/* Normal notification (task_done) */
-		dev_dbg(task->dev->port->ha->dev,
-			"%s: Normal - task = %p, response=%d, status=%d\n",
-			__func__, task, response, status);
-		task->task_done(task);
-		task->lldd_task = NULL;
-		break;
-
-	case isci_perform_aborted_io_completion:
-		/* No notification because this request is already in the
-		 * abort path.
-		 */
-		dev_warn(task->dev->port->ha->dev,
-			 "%s: Aborted - task = %p, response=%d, status=%d\n",
-			 __func__, task, response, status);
-		break;
-
-	case isci_perform_error_io_completion:
-		/* Use sas_task_abort */
-		dev_warn(task->dev->port->ha->dev,
-			 "%s: Error - task = %p, response=%d, status=%d\n",
-			 __func__, task, response, status);
-		sas_task_abort(task);
-		break;
-
-	default:
-		dev_warn(task->dev->port->ha->dev,
-			 "%s: isci task notification default case!",
-			 __func__);
-		sas_task_abort(task);
-		break;
-	}
 }
 
 #endif /* !defined(_SCI_TASK_H_) */
diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c
index ca72308..f33eff0 100644
--- a/drivers/scsi/isci/timers.c
+++ b/drivers/scsi/isci/timers.c
@@ -56,96 +56,59 @@
 #include "isci.h"
 #include "timers.h"
 
-
 /**
  * isci_timer_list_construct() - This method contrucst the SCI Timer List
  *    object used by the SCI Module class. The construction process involves
  *    creating isci_timer objects and adding them to the SCI Timer List
  *    object's list member. The number of isci_timer objects is determined by
  *    the timer_list_size parameter.
- * @isci_timer_list: This parameter points to the SCI Timer List object being
- *    constructed. The calling routine is responsible for allocating the memory
- *    for isci_timer_list and initializing the timer list_head member of
- *    isci_timer_list.
- * @timer_list_size: This parameter specifies the number of isci_timer objects
- *    contained by the SCI Timer List. which this timer is to be associated.
+ * @ihost: container of the timer list
  *
  * This method returns an error code indicating sucess or failure. The user
  * should check for possible memory allocation error return otherwise, a zero
  * indicates success.
  */
-int isci_timer_list_construct(
-	struct isci_timer_list *isci_timer_list,
-	int timer_list_size)
+int isci_timer_list_construct(struct isci_host *ihost)
 {
-	struct isci_timer *isci_timer;
-	int i;
-	int err = 0;
-
+	struct isci_timer *itimer;
+	int i, err = 0;
 
-	for (i = 0; i < timer_list_size; i++) {
-
-		isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL);
-
-		if (!isci_timer) {
+	INIT_LIST_HEAD(&ihost->timers);
+	for (i = 0; i < SCI_MAX_TIMER_COUNT; i++) {
+		itimer = devm_kzalloc(&ihost->pdev->dev, sizeof(*itimer), GFP_KERNEL);
 
+		if (!itimer) {
 			err = -ENOMEM;
 			break;
 		}
-		isci_timer->used = 0;
-		isci_timer->stopped = 1;
-		isci_timer->parent = isci_timer_list;
-		list_add(&isci_timer->node, &isci_timer_list->timers);
+		init_timer(&itimer->timer);
+		itimer->used = 0;
+		itimer->stopped = 1;
+		list_add(&itimer->node, &ihost->timers);
 	}
 
-	return 0;
-
+	return err;
 }
 
-
 /**
  * isci_timer_list_destroy() - This method destroys the SCI Timer List object
  *    used by the SCI Module class. The destruction  process involves freeing
  *    memory allocated for isci_timer objects on the SCI Timer List object's
  *    timers list_head member. If any isci_timer objects are mark as "in use",
  *    they are not freed and the function returns an error code of -EBUSY.
- * @isci_timer_list: This parameter points to the SCI Timer List object being
- *    destroyed.
- *
- * This method returns an error code indicating sucess or failure. The user
- * should check for possible -EBUSY error return, in the event of one or more
- * isci_timers still "in use", otherwise, a zero indicates success.
+ * @ihost: container of the list to be destroyed
  */
-int isci_timer_list_destroy(
-	struct isci_timer_list *isci_timer_list)
+void isci_timer_list_destroy(struct isci_host *ihost)
 {
-	struct isci_timer *timer, *tmp;
-
-	list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) {
-		isci_timer_free(isci_timer_list, timer);
-		list_del(&timer->node);
-		kfree(timer);
-	}
-	return 0;
-}
+	struct isci_timer *timer;
+	LIST_HEAD(list);
 
+	spin_lock_irq(&ihost->scic_lock);
+	list_splice_init(&ihost->timers, &list);
+	spin_unlock_irq(&ihost->scic_lock);
 
-
-static void isci_timer_restart(struct isci_timer *isci_timer)
-{
-	struct timer_list *timer =
-		&isci_timer->timer;
-	unsigned long timeout;
-
-	dev_dbg(&isci_timer->isci_host->pdev->dev,
-		"%s: isci_timer = %p\n", __func__, isci_timer);
-
-	isci_timer->restart = 0;
-	isci_timer->stopped = 0;
-	timeout = isci_timer->timeout_value;
-	timeout = (timeout * HZ) / 1000;
-	timeout = timeout ? timeout : 1;
-	mod_timer(timer, jiffies + timeout);
+	list_for_each_entry(timer, &list, node)
+		del_timer_sync(&timer->timer);
 }
 
 /**
@@ -169,7 +132,7 @@ static void isci_timer_restart(struct isci_timer *isci_timer)
 static void timer_function(unsigned long data)
 {
 
-	struct isci_timer *timer     = (struct isci_timer *)data;
+	struct isci_timer *timer = (struct isci_timer *)data;
 	struct isci_host *isci_host = timer->isci_host;
 	unsigned long flags;
 
@@ -185,89 +148,66 @@ static void timer_function(unsigned long data)
 
 	if (!timer->stopped) {
 		timer->stopped = 1;
-		timer->timer_callback(timer->cookie);
-
-		if (timer->restart)
-			isci_timer_restart(timer);
+		timer->timer_callback(timer->cb_param);
 	}
 
 	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 }
 
 
-struct isci_timer *isci_timer_create(
-	struct isci_timer_list *isci_timer_list,
-	struct isci_host *isci_host,
-	void *cookie,
-	void (*timer_callback)(void *))
+struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param,
+				     void (*timer_callback)(void *))
 {
-
 	struct timer_list *timer;
 	struct isci_timer *isci_timer;
-	struct list_head *timer_list =
-		&isci_timer_list->timers;
-	unsigned long flags;
+	struct list_head *list = &ihost->timers;
 
-	spin_lock_irqsave(&isci_host->scic_lock, flags);
+	WARN_ONCE(!spin_is_locked(&ihost->scic_lock),
+		  "%s: unlocked!\n", __func__);
 
-	if (list_empty(timer_list)) {
-		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+	if (WARN_ONCE(list_empty(list), "%s: timer pool empty\n", __func__))
 		return NULL;
-	}
 
-	isci_timer = list_entry(timer_list->next, struct isci_timer, node);
+	isci_timer = list_entry(list->next, struct isci_timer, node);
 
-	if (isci_timer->used) {
-		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
-		return NULL;
-	}
 	isci_timer->used = 1;
 	isci_timer->stopped = 1;
-	list_move_tail(&isci_timer->node, timer_list);
-
-	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+	/* FIXME: what!? we recycle the timer, rather than take it off
+	 * the free list?
+	 */
+	list_move_tail(&isci_timer->node, list);
 
 	timer = &isci_timer->timer;
 	timer->data = (unsigned long)isci_timer;
 	timer->function = timer_function;
-	isci_timer->cookie = cookie;
+	isci_timer->cb_param = cb_param;
 	isci_timer->timer_callback = timer_callback;
-	isci_timer->isci_host = isci_host;
+	isci_timer->isci_host = ihost;
 
-	dev_dbg(&isci_host->pdev->dev,
+	dev_dbg(&ihost->pdev->dev,
 		"%s: isci_timer = %p\n", __func__, isci_timer);
 
 	return isci_timer;
 }
 
-/**
- * isci_timer_free() - This method frees the isci_timer, marking it "free to
+/* isci_del_timer() - This method frees the isci_timer, marking it "free to
  *    use", then places its back at the head of the timers list for the SCI
  *    Timer List object specified.
- * @isci_timer_list: This parameter points to the SCI Timer List from which the
- *    timer is reserved.
- * @isci_timer: This parameter specifies the timer to be freed.
- *
  */
-void isci_timer_free(
-	struct isci_timer_list *isci_timer_list,
-	struct isci_timer *isci_timer)
+void isci_del_timer(struct isci_host *ihost, struct isci_timer *isci_timer)
 {
-	struct list_head *timer_list = &isci_timer_list->timers;
+	struct list_head *list = &ihost->timers;
+
+	WARN_ONCE(!spin_is_locked(&ihost->scic_lock),
+		  "%s unlocked!\n", __func__);
 
 	dev_dbg(&isci_timer->isci_host->pdev->dev,
 		"%s: isci_timer = %p\n", __func__, isci_timer);
 
-	if (list_empty(timer_list))
-		return;
-
 	isci_timer->used = 0;
-	list_move(&isci_timer->node, timer_list);
-
-	if (!isci_timer->stopped) {
-		del_timer(&isci_timer->timer);
-		isci_timer->stopped = 1;
-	}
+	list_move(&isci_timer->node, list);
+	del_timer(&isci_timer->timer);
+	isci_timer->stopped = 1;
 }
 
 /**
@@ -278,26 +218,15 @@ void isci_timer_free(
  *    the associated callback function will be called.
  *
  */
-void isci_timer_start(
-	struct isci_timer *isci_timer,
-	unsigned long timeout)
+void isci_timer_start(struct isci_timer *isci_timer, unsigned long tmo)
 {
 	struct timer_list *timer = &isci_timer->timer;
 
 	dev_dbg(&isci_timer->isci_host->pdev->dev,
 		"%s: isci_timer = %p\n", __func__, isci_timer);
 
-	isci_timer->timeout_value = timeout;
-	init_timer(timer);
-	timeout = (timeout * HZ) / 1000;
-	timeout = timeout ? timeout : 1;
-
-	timer->expires = jiffies + timeout;
-	timer->data = (unsigned long)isci_timer;
-	timer->function = timer_function;
 	isci_timer->stopped = 0;
-	isci_timer->restart = 0;
-	add_timer(timer);
+	mod_timer(timer, jiffies + msecs_to_jiffies(tmo));
 }
 
 /**
@@ -310,10 +239,6 @@ void isci_timer_stop(struct isci_timer *isci_timer)
 	dev_dbg(&isci_timer->isci_host->pdev->dev,
 		"%s: isci_timer = %p\n", __func__, isci_timer);
 
-	if (isci_timer->stopped)
-		return;
-
 	isci_timer->stopped = 1;
-
 	del_timer(&isci_timer->timer);
 }
diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h
index ca5c215..8d8a892 100644
--- a/drivers/scsi/isci/timers.h
+++ b/drivers/scsi/isci/timers.h
@@ -59,68 +59,30 @@
 #include <linux/timer.h>
 #include <linux/types.h>
 
-/***************************************************
- * isci_timer
- ***************************************************
- */
-/**
- * struct isci_timer_list - This class is the container for all isci_timer
- *    objects
- *
- *
- */
-struct isci_timer_list {
-
-	struct list_head timers;
-};
+#define SCI_MAX_TIMER_COUNT 25
 
 /**
  * struct isci_timer - This class represents the timer object used by SCIC. It
- *    wraps the Linux timer_list object.
- *
+ *    wraps the Linux timer_list object, and (TODO) should be removed in favor
+ *    of a delayed-workqueue style interface with simpler locking
  *
  */
 struct isci_timer {
 	int used;
 	int stopped;
-	int restart;
-	int timeout_value;
-	void *cookie;
+	void *cb_param;
 	void (*timer_callback)(void *);
 	struct list_head node;
 	struct timer_list timer;
-	struct isci_timer_list *parent;
 	struct isci_host *isci_host;
 };
 
-#define to_isci_timer(t)	\
-	container_of(t, struct isci_timer, timer);
-
-int isci_timer_list_construct(
-	struct isci_timer_list *isci_timer_list,
-	int timer_list_size);
-
-
-int isci_timer_list_destroy(
-	struct isci_timer_list *isci_timer_list);
-
-struct isci_timer *isci_timer_create(
-	struct isci_timer_list *isci_timer_list,
-	struct isci_host *isci_host,
-	void *cookie,
-	void (*timer_callback)(void *));
-
-void isci_timer_free(
-	struct isci_timer_list *isci_timer_list,
-	struct isci_timer *isci_timer);
-
-void isci_timer_start(
-	struct isci_timer *isci_timer,
-	unsigned long timeout);
-
-void isci_timer_stop(
-	struct isci_timer *isci_timer);
-
+int isci_timer_list_construct(struct isci_host *ihost);
+void isci_timer_list_destroy(struct isci_host *ihost);
+struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param,
+				     void (*timer_callback)(void *));
+void isci_del_timer(struct isci_host *ihost, struct isci_timer *itimer);
+void isci_timer_start(struct isci_timer *isci_timer, unsigned long timeout);
+void isci_timer_stop(struct isci_timer *isci_timer);
 
 #endif /* !defined (_SCI_TIMER_H_) */
-


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux