[kernel] r19726 - in dists/squeeze/linux-2.6/debian: . patches/features/x86/isci patches/series

Ben Hutchings benh at alioth.debian.org
Mon Jan 14 01:10:01 UTC 2013


Author: benh
Date: Mon Jan 14 01:10:00 2013
New Revision: 19726

Log:
[x86] isci: Backport changes up to Linux 3.2.35 (Closes: #698094)

Added:
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0002-treewide-remove-extra-semicolons-from-various-parts-.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0005-SCSI-isci-fix-support-for-large-smp-requests.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0006-SCSI-isci-fix-missed-unlock-in-apc_agent_timeout.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0007-SCSI-isci-atapi-support.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0008-SCSI-isci-SATA-STP-I-O-is-only-returned-in-the-norma.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0009-SCSI-isci-fix-decode-of-DONE_CRC_ERR-TC-completion-s.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0010-SCSI-isci-The-port-state-should-be-set-to-stopping-o.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0012-SCSI-isci-Lookup-device-references-through-requests-.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0013-SCSI-isci-Immediately-fail-I-O-to-removed-devices.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0014-SCSI-isci-Fix-tag-leak-in-tasks-and-terminated-reque.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0015-SCSI-isci-Handle-task-request-timeouts-correctly.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0016-SCSI-isci-No-task_done-callbacks-in-error-handler-pa.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0017-SCSI-isci-Fix-task-management-for-SMP-SATA-and-on-de.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0018-SCSI-isci-Remove-redundant-isci_request.ttype-field.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0019-SCSI-isci-No-need-to-manage-the-pending-reset-bit-on.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0020-SCSI-isci-Fix-hard-reset-timeout-conditions.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0021-SCSI-isci-revert-bcn-filtering.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0022-SCSI-isci-overriding-max_concurr_spinup-oem-paramete.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0023-isci-fix-oem-parameter-validation-on-single-controll.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0024-isci-fix-isci_pci_probe-generates-warning-on-efi-fai.patch
   dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0025-isci-copy-fis-0x34-response-into-proper-buffer.patch
Modified:
   dists/squeeze/linux-2.6/debian/changelog
   dists/squeeze/linux-2.6/debian/patches/series/47

Modified: dists/squeeze/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze/linux-2.6/debian/changelog	Sun Jan 13 00:12:05 2013	(r19725)
+++ dists/squeeze/linux-2.6/debian/changelog	Mon Jan 14 01:10:00 2013	(r19726)
@@ -80,6 +80,7 @@
   * [x86] Don't use the EFI reboot method by default (Closes: #626022)
   * [x86] drm/i915: Attempt to fix watermark setup on 85x (v2)
     (Closes: #661696)
+  * [x86] isci: Backport changes up to Linux 3.2.35 (Closes: #698094)
 
   [ Jonathan Nieder ]
   * megaraid_sas: Backport changes up to Linux 3.0.56 (Closes: #666108)

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0002-treewide-remove-extra-semicolons-from-various-parts-.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0002-treewide-remove-extra-semicolons-from-various-parts-.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,31 @@
+From: "Justin P. Mattock" <justinmattock at gmail.com>
+Date: Tue, 26 Jul 2011 23:06:29 -0700
+Subject: [02/25] treewide: remove extra semicolons from various parts of the
+ kernel
+
+commit 699324871fcc3650f2023c5e36cb119a92d7894b upstream.
+
+This is a resend from the original, changing the title from PATCH to
+RFC(since this is a review for commit, and I should have put that the first go around).
+and also removing some of the commit's with ia64 and bash since it is significant.
+let me know if I might have missed anything etc..
+
+Signed-off-by: Justin P. Mattock <justinmattock at gmail.com>
+Signed-off-by: Jiri Kosina <jkosina at suse.cz>
+---
+ drivers/scsi/isci/phy.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
+index 79313a7..8d9192d 100644
+--- a/drivers/scsi/isci/phy.c
++++ b/drivers/scsi/isci/phy.c
+@@ -695,7 +695,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
+ 				 __func__,
+ 				 event_code);
+ 
+-			return SCI_FAILURE;;
++			return SCI_FAILURE;
+ 		}
+ 		return SCI_SUCCESS;
+ 	case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0005-SCSI-isci-fix-support-for-large-smp-requests.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0005-SCSI-isci-fix-support-for-large-smp-requests.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,149 @@
+From: Dan Williams <dan.j.williams at intel.com>
+Date: Wed, 28 Sep 2011 18:35:27 -0700
+Subject: [05/25] [SCSI] isci: fix support for large smp requests
+
+commit 54b5e3a4bfa3452bc10cd4da672099ccc46b8c09 upstream.
+
+Kill the local smp response buffer.
+
+Besides being unnecessary, it is too small (currently truncates
+responses to 60 bytes).  The mid-layer will have already allocated a
+sufficiently sized buffer, just kmap and copy into it directly.
+
+Reported-by: Derick Marks <derick.w.marks at intel.com>
+Tested-by: Derick Marks <derick.w.marks at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/isci.h    |    2 +-
+ drivers/scsi/isci/request.c |   49 ++++++++++++++++++-------------------------
+ drivers/scsi/isci/request.h |    3 ---
+ drivers/scsi/isci/sas.h     |    2 --
+ 4 files changed, 21 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
+index d1de633..8efeb6b 100644
+--- a/drivers/scsi/isci/isci.h
++++ b/drivers/scsi/isci/isci.h
+@@ -97,7 +97,7 @@
+ #define SCU_MAX_COMPLETION_QUEUE_SHIFT	  (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
+ 
+ #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
+-#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024)
++#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024U)
+ #define SCU_INVALID_FRAME_INDEX             (0xFFFF)
+ 
+ #define SCU_IO_REQUEST_MAX_SGE_SIZE         (0x00FFFFFF)
+diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
+index b5d3a8c..225b196 100644
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -1490,29 +1490,30 @@ sci_io_request_frame_handler(struct isci_request *ireq,
+ 		return SCI_SUCCESS;
+ 
+ 	case SCI_REQ_SMP_WAIT_RESP: {
+-		struct smp_resp *rsp_hdr = &ireq->smp.rsp;
+-		void *frame_header;
++		struct sas_task *task = isci_request_access_task(ireq);
++		struct scatterlist *sg = &task->smp_task.smp_resp;
++		void *frame_header, *kaddr;
++		u8 *rsp;
+ 
+ 		sci_unsolicited_frame_control_get_header(&ihost->uf_control,
+-							      frame_index,
+-							      &frame_header);
+-
+-		/* byte swap the header. */
+-		word_cnt = SMP_RESP_HDR_SZ / sizeof(u32);
+-		sci_swab32_cpy(rsp_hdr, frame_header, word_cnt);
++							 frame_index,
++							 &frame_header);
++		kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
++		rsp = kaddr + sg->offset;
++		sci_swab32_cpy(rsp, frame_header, 1);
+ 
+-		if (rsp_hdr->frame_type == SMP_RESPONSE) {
++		if (rsp[0] == SMP_RESPONSE) {
+ 			void *smp_resp;
+ 
+ 			sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
+-								      frame_index,
+-								      &smp_resp);
++								 frame_index,
++								 &smp_resp);
+ 
+-			word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) /
+-				sizeof(u32);
+-
+-			sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ,
+-				       smp_resp, word_cnt);
++			word_cnt = (sg->length/4)-1;
++			if (word_cnt > 0)
++				word_cnt = min_t(unsigned int, word_cnt,
++						 SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4);
++			sci_swab32_cpy(rsp + 4, smp_resp, word_cnt);
+ 
+ 			ireq->scu_status = SCU_TASK_DONE_GOOD;
+ 			ireq->sci_status = SCI_SUCCESS;
+@@ -1528,12 +1529,13 @@ sci_io_request_frame_handler(struct isci_request *ireq,
+ 				__func__,
+ 				ireq,
+ 				frame_index,
+-				rsp_hdr->frame_type);
++				rsp[0]);
+ 
+ 			ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR;
+ 			ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
+ 			sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ 		}
++		kunmap_atomic(kaddr, KM_IRQ0);
+ 
+ 		sci_controller_release_frame(ihost, frame_index);
+ 
+@@ -2603,18 +2605,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
+ 			status   = SAM_STAT_GOOD;
+ 			set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+ 
+-			if (task->task_proto == SAS_PROTOCOL_SMP) {
+-				void *rsp = &request->smp.rsp;
+-
+-				dev_dbg(&ihost->pdev->dev,
+-					"%s: SMP protocol completion\n",
+-					__func__);
+-
+-				sg_copy_from_buffer(
+-					&task->smp_task.smp_resp, 1,
+-					rsp, sizeof(struct smp_resp));
+-			} else if (completion_status
+-				   == SCI_IO_SUCCESS_IO_DONE_EARLY) {
++			if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
+ 
+ 				/* This was an SSP / STP / SATA transfer.
+ 				 * There is a possibility that less data than
+diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
+index 7a1d5a9..58d70b6 100644
+--- a/drivers/scsi/isci/request.h
++++ b/drivers/scsi/isci/request.h
+@@ -174,9 +174,6 @@ struct isci_request {
+ 			};
+ 		} ssp;
+ 		struct {
+-			struct smp_resp rsp;
+-		} smp;
+-		struct {
+ 			struct isci_stp_request req;
+ 			struct host_to_dev_fis cmd;
+ 			struct dev_to_host_fis rsp;
+diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h
+index 462b151..dc26b4a 100644
+--- a/drivers/scsi/isci/sas.h
++++ b/drivers/scsi/isci/sas.h
+@@ -204,8 +204,6 @@ struct smp_req {
+ 	u8 req_data[0];
+ }  __packed;
+ 
+-#define SMP_RESP_HDR_SZ	4
+-
+ /*
+  * struct sci_sas_address - This structure depicts how a SAS address is
+  *    represented by SCI.

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0006-SCSI-isci-fix-missed-unlock-in-apc_agent_timeout.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0006-SCSI-isci-fix-missed-unlock-in-apc_agent_timeout.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,30 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Wed, 28 Sep 2011 18:35:32 -0700
+Subject: [06/25] [SCSI] isci: fix missed unlock in apc_agent_timeout()
+
+commit 983d3fdd332742167d0482c06fd29cf4b8a687c0 upstream.
+
+Needed to jump to scic_lock unlock.
+
+Also spotted by coccicheck.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/port_config.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c
+index 486b113..38a99d2 100644
+--- a/drivers/scsi/isci/port_config.c
++++ b/drivers/scsi/isci/port_config.c
+@@ -678,7 +678,7 @@ static void apc_agent_timeout(unsigned long data)
+ 	configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+ 
+ 	if (!configure_phy_mask)
+-		return;
++		goto done;
+ 
+ 	for (index = 0; index < SCI_MAX_PHYS; index++) {
+ 		if ((configure_phy_mask & (1 << index)) == 0)

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0007-SCSI-isci-atapi-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0007-SCSI-isci-atapi-support.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,626 @@
+From: Dan Williams <dan.j.williams at intel.com>
+Date: Fri, 30 Sep 2011 18:52:19 -0700
+Subject: [07/25] [SCSI] isci: atapi support
+
+commit b50102d3e9a43a75379407c2080f696f61cb286b upstream.
+
+Based on original implementation from Jiangbi Liu and Maciej Trela.
+
+ATAPI transfers happen in two-to-three stages.  The two stage atapi
+commands are those that include a dma data transfer.  The data transfer
+portion of these operations is handled by the hardware packet-dma
+acceleration.  The three-stage commands do not have a data transfer and
+are handled without hardware assistance in raw frame mode.
+
+stage1: transmit host-to-device fis to notify the device of an incoming
+atapi cdb.  Upon reception of the pio-setup-fis repost the task_context
+to perform the dma transfer of the cdb+data (go to stage3), or repost
+the task_context to transmit the cdb as a raw frame (go to stage 2).
+
+stage2: wait for hardware notification of the cdb transmission and then
+go to stage 3.
+
+stage3: wait for the arrival of the terminating device-to-host fis and
+terminate the command.
+
+To keep the implementation simple we only support ATAPI packet-dma
+protocol (for commands with data) to avoid needing to handle the data
+transfer manually (like we do for SATA-PIO).  This may affect
+compatibility for a small number of devices (see
+ATA_HORKAGE_ATAPI_MOD16_DMA).
+
+If the data-transfer underruns, or encounters an error the
+device-to-host fis is expected to arrive in the unsolicited frame queue
+to pass to libata for disposition.  However, in the DONE_UNEXP_FIS (data
+underrun) case it appears we need to craft a response.  In the
+DONE_REG_ERR case we do receive the UF and propagate it to libsas.
+
+Signed-off-by: Maciej Trela <maciej.trela at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+[bwh: Backported to 2.6.32: drop change to drivers/scsi/libsas/sas_scsi_host.c]
+---
+--- a/drivers/scsi/isci/remote_device.c
++++ b/drivers/scsi/isci/remote_device.c
+@@ -386,6 +386,18 @@ static bool is_remote_device_ready(struct isci_remote_device *idev)
+ 	}
+ }
+ 
++/*
++ * called once the remote node context has transisitioned to a ready
++ * state (after suspending RX and/or TX due to early D2H fis)
++ */
++static void atapi_remote_device_resume_done(void *_dev)
++{
++	struct isci_remote_device *idev = _dev;
++	struct isci_request *ireq = idev->working_request;
++
++	sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
++}
++
+ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
+ 						     u32 event_code)
+ {
+@@ -432,6 +444,16 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
+ 	if (status != SCI_SUCCESS)
+ 		return status;
+ 
++	if (state == SCI_STP_DEV_ATAPI_ERROR) {
++		/* For ATAPI error state resume the RNC right away. */
++		if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
++		    scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
++			return sci_remote_node_context_resume(&idev->rnc,
++							      atapi_remote_device_resume_done,
++							      idev);
++		}
++	}
++
+ 	if (state == SCI_STP_DEV_IDLE) {
+ 
+ 		/* We pick up suspension events to handle specifically to this
+@@ -625,6 +647,7 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost,
+ 	case SCI_STP_DEV_CMD:
+ 	case SCI_STP_DEV_NCQ:
+ 	case SCI_STP_DEV_NCQ_ERROR:
++	case SCI_STP_DEV_ATAPI_ERROR:
+ 		status = common_complete_io(iport, idev, ireq);
+ 		if (status != SCI_SUCCESS)
+ 			break;
+@@ -1020,6 +1043,7 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
+ 	[SCI_STP_DEV_NCQ_ERROR] = {
+ 		.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
+ 	},
++	[SCI_STP_DEV_ATAPI_ERROR] = { },
+ 	[SCI_STP_DEV_AWAIT_RESET] = { },
+ 	[SCI_SMP_DEV_IDLE] = {
+ 		.enter_state = sci_smp_remote_device_ready_idle_substate_enter,
+--- a/drivers/scsi/isci/remote_device.h
++++ b/drivers/scsi/isci/remote_device.h
+@@ -244,6 +244,15 @@ enum sci_remote_device_states {
+ 	SCI_STP_DEV_NCQ_ERROR,
+ 
+ 	/**
++	 * This is the ATAPI error state for the STP ATAPI remote device.
++	 * This state is entered when ATAPI device sends error status FIS
++	 * without data while the device object is in CMD state.
++	 * A suspension event is expected in this state.
++	 * The device object will resume right away.
++	 */
++	SCI_STP_DEV_ATAPI_ERROR,
++
++	/**
+ 	 * This is the READY substate indicates the device is waiting for the RESET task
+ 	 * coming to be recovered from certain hardware specific error.
+ 	 */
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -481,7 +481,29 @@ static void sci_stp_optimized_request_construct(struct isci_request *ireq,
+ 	}
+ }
+ 
++static void sci_atapi_construct(struct isci_request *ireq)
++{
++	struct host_to_dev_fis *h2d_fis = &ireq->stp.cmd;
++	struct sas_task *task;
++
++	/* To simplify the implementation we take advantage of the
++	 * silicon's partial acceleration of atapi protocol (dma data
++	 * transfers), so we promote all commands to dma protocol.  This
++	 * breaks compatibility with ATA_HORKAGE_ATAPI_MOD16_DMA drives.
++	 */
++	h2d_fis->features |= ATAPI_PKT_DMA;
++
++	scu_stp_raw_request_construct_task_context(ireq);
++
++	task = isci_request_access_task(ireq);
++	if (task->data_dir == DMA_NONE)
++		task->total_xfer_len = 0;
+ 
++	/* clear the response so we can detect arrivial of an
++	 * unsolicited h2d fis
++	 */
++	ireq->stp.rsp.fis_type = 0;
++}
+ 
+ static enum sci_status
+ sci_io_request_construct_sata(struct isci_request *ireq,
+@@ -491,6 +513,7 @@ sci_io_request_construct_sata(struct isci_request *ireq,
+ {
+ 	enum sci_status status = SCI_SUCCESS;
+ 	struct sas_task *task = isci_request_access_task(ireq);
++	struct domain_device *dev = ireq->target_device->domain_dev;
+ 
+ 	/* check for management protocols */
+ 	if (ireq->ttype == tmf_task) {
+@@ -519,6 +542,13 @@ sci_io_request_construct_sata(struct isci_request *ireq,
+ 
+ 	}
+ 
++	/* ATAPI */
++	if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
++	    task->ata_task.fis.command == ATA_CMD_PACKET) {
++		sci_atapi_construct(ireq);
++		return SCI_SUCCESS;
++	}
++
+ 	/* non data */
+ 	if (task->data_dir == DMA_NONE) {
+ 		scu_stp_raw_request_construct_task_context(ireq);
+@@ -627,7 +657,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
+ 
+ /**
+  * sci_req_tx_bytes - bytes transferred when reply underruns request
+- * @sci_req: request that was terminated early
++ * @ireq: request that was terminated early
+  */
+ #define SCU_TASK_CONTEXT_SRAM 0x200000
+ static u32 sci_req_tx_bytes(struct isci_request *ireq)
+@@ -729,6 +759,10 @@ sci_io_request_terminate(struct isci_request *ireq)
+ 	case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED:
+ 	case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG:
+ 	case SCI_REQ_STP_SOFT_RESET_WAIT_D2H:
++	case SCI_REQ_ATAPI_WAIT_H2D:
++	case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
++	case SCI_REQ_ATAPI_WAIT_D2H:
++	case SCI_REQ_ATAPI_WAIT_TC_COMP:
+ 		sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
+ 		return SCI_SUCCESS;
+ 	case SCI_REQ_TASK_WAIT_TC_RESP:
+@@ -1194,8 +1228,8 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
+ {
+ 	struct isci_stp_request *stp_req = &ireq->stp.req;
+ 	struct scu_sgl_element_pair *sgl_pair;
++	enum sci_status status = SCI_SUCCESS;
+ 	struct scu_sgl_element *sgl;
+-	enum sci_status status;
+ 	u32 offset;
+ 	u32 len = 0;
+ 
+@@ -1249,7 +1283,7 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
+  */
+ static enum sci_status
+ sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req,
+-						  u8 *data_buf, u32 len)
++					     u8 *data_buf, u32 len)
+ {
+ 	struct isci_request *ireq;
+ 	u8 *src_addr;
+@@ -1423,6 +1457,128 @@ static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_re
+ 	return status;
+ }
+ 
++static enum sci_status process_unsolicited_fis(struct isci_request *ireq,
++					       u32 frame_index)
++{
++	struct isci_host *ihost = ireq->owning_controller;
++	enum sci_status status;
++	struct dev_to_host_fis *frame_header;
++	u32 *frame_buffer;
++
++	status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
++							  frame_index,
++							  (void **)&frame_header);
++
++	if (status != SCI_SUCCESS)
++		return status;
++
++	if (frame_header->fis_type != FIS_REGD2H) {
++		dev_err(&ireq->isci_host->pdev->dev,
++			"%s ERROR: invalid fis type 0x%X\n",
++			__func__, frame_header->fis_type);
++		return SCI_FAILURE;
++	}
++
++	sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
++						 frame_index,
++						 (void **)&frame_buffer);
++
++	sci_controller_copy_sata_response(&ireq->stp.rsp,
++					  (u32 *)frame_header,
++					  frame_buffer);
++
++	/* Frame has been decoded return it to the controller */
++	sci_controller_release_frame(ihost, frame_index);
++
++	return status;
++}
++
++static enum sci_status atapi_d2h_reg_frame_handler(struct isci_request *ireq,
++						   u32 frame_index)
++{
++	struct sas_task *task = isci_request_access_task(ireq);
++	enum sci_status status;
++
++	status = process_unsolicited_fis(ireq, frame_index);
++
++	if (status == SCI_SUCCESS) {
++		if (ireq->stp.rsp.status & ATA_ERR)
++			status = SCI_IO_FAILURE_RESPONSE_VALID;
++	} else {
++		status = SCI_IO_FAILURE_RESPONSE_VALID;
++	}
++
++	if (status != SCI_SUCCESS) {
++		ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
++		ireq->sci_status = status;
++	} else {
++		ireq->scu_status = SCU_TASK_DONE_GOOD;
++		ireq->sci_status = SCI_SUCCESS;
++	}
++
++	/* the d2h ufi is the end of non-data commands */
++	if (task->data_dir == DMA_NONE)
++		sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
++
++	return status;
++}
++
++static void scu_atapi_reconstruct_raw_frame_task_context(struct isci_request *ireq)
++{
++	struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
++	void *atapi_cdb = ireq->ttype_ptr.io_task_ptr->ata_task.atapi_packet;
++	struct scu_task_context *task_context = ireq->tc;
++
++	/* fill in the SCU Task Context for a DATA fis containing CDB in Raw Frame
++	 * type. The TC for previous Packet fis was already there, we only need to
++	 * change the H2D fis content.
++	 */
++	memset(&ireq->stp.cmd, 0, sizeof(struct host_to_dev_fis));
++	memcpy(((u8 *)&ireq->stp.cmd + sizeof(u32)), atapi_cdb, ATAPI_CDB_LEN);
++	memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context));
++	task_context->type.stp.fis_type = FIS_DATA;
++	task_context->transfer_length_bytes = dev->cdb_len;
++}
++
++static void scu_atapi_construct_task_context(struct isci_request *ireq)
++{
++	struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
++	struct sas_task *task = isci_request_access_task(ireq);
++	struct scu_task_context *task_context = ireq->tc;
++	int cdb_len = dev->cdb_len;
++
++	/* reference: SSTL 1.13.4.2
++	 * task_type, sata_direction
++	 */
++	if (task->data_dir == DMA_TO_DEVICE) {
++		task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
++		task_context->sata_direction = 0;
++	} else {
++		/* todo: for NO_DATA command, we need to send out raw frame. */
++		task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
++		task_context->sata_direction = 1;
++	}
++
++	memset(&task_context->type.stp, 0, sizeof(task_context->type.stp));
++	task_context->type.stp.fis_type = FIS_DATA;
++
++	memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
++	memcpy(&ireq->stp.cmd.lbal, task->ata_task.atapi_packet, cdb_len);
++	task_context->ssp_command_iu_length = cdb_len / sizeof(u32);
++
++	/* task phase is set to TX_CMD */
++	task_context->task_phase = 0x1;
++
++	/* retry counter */
++	task_context->stp_retry_count = 0;
++
++	/* data transfer size. */
++	task_context->transfer_length_bytes = task->total_xfer_len;
++
++	/* setup sgl */
++	sci_request_build_sgl(ireq);
++}
++
+ enum sci_status
+ sci_io_request_frame_handler(struct isci_request *ireq,
+ 				  u32 frame_index)
+@@ -1835,6 +1991,24 @@ sci_io_request_frame_handler(struct isci_request *ireq,
+ 
+ 		return status;
+ 	}
++	case SCI_REQ_ATAPI_WAIT_PIO_SETUP: {
++		struct sas_task *task = isci_request_access_task(ireq);
++
++		sci_controller_release_frame(ihost, frame_index);
++		ireq->target_device->working_request = ireq;
++		if (task->data_dir == DMA_NONE) {
++			sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_TC_COMP);
++			scu_atapi_reconstruct_raw_frame_task_context(ireq);
++		} else {
++			sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
++			scu_atapi_construct_task_context(ireq);
++		}
++
++		sci_controller_continue_io(ireq);
++		return SCI_SUCCESS;
++	}
++	case SCI_REQ_ATAPI_WAIT_D2H:
++		return atapi_d2h_reg_frame_handler(ireq, frame_index);
+ 	case SCI_REQ_ABORTING:
+ 		/*
+ 		 * TODO: Is it even possible to get an unsolicited frame in the
+@@ -1966,6 +2140,112 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq,
+ 	return SCI_SUCCESS;
+ }
+ 
++static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code,
++						  enum sci_base_request_states next)
++{
++	enum sci_status status = SCI_SUCCESS;
++
++	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
++	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
++		ireq->scu_status = SCU_TASK_DONE_GOOD;
++		ireq->sci_status = SCI_SUCCESS;
++		sci_change_state(&ireq->sm, next);
++		break;
++	default:
++		/* All other completion status cause the IO to be complete.
++		 * If a NAK was received, then it is up to the user to retry
++		 * the request.
++		 */
++		ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
++		ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
++
++		sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
++		break;
++	}
++
++	return status;
++}
++
++static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ireq,
++							u32 completion_code)
++{
++	struct isci_remote_device *idev = ireq->target_device;
++	struct dev_to_host_fis *d2h = &ireq->stp.rsp;
++	enum sci_status status = SCI_SUCCESS;
++
++	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
++	case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
++		sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
++		break;
++
++	case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): {
++		u16 len = sci_req_tx_bytes(ireq);
++
++		/* likely non-error data underrrun, workaround missing
++		 * d2h frame from the controller
++		 */
++		if (d2h->fis_type != FIS_REGD2H) {
++			d2h->fis_type = FIS_REGD2H;
++			d2h->flags = (1 << 6);
++			d2h->status = 0x50;
++			d2h->error = 0;
++			d2h->lbal = 0;
++			d2h->byte_count_low = len & 0xff;
++			d2h->byte_count_high = len >> 8;
++			d2h->device = 0xa0;
++			d2h->lbal_exp = 0;
++			d2h->lbam_exp = 0;
++			d2h->lbah_exp = 0;
++			d2h->_r_a = 0;
++			d2h->sector_count = 0x3;
++			d2h->sector_count_exp = 0;
++			d2h->_r_b = 0;
++			d2h->_r_c = 0;
++			d2h->_r_d = 0;
++		}
++
++		ireq->scu_status = SCU_TASK_DONE_GOOD;
++		ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY;
++		status = ireq->sci_status;
++
++		/* the hw will have suspended the rnc, so complete the
++		 * request upon pending resume
++		 */
++		sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
++		break;
++	}
++	case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
++		/* In this case, there is no UF coming after.
++		 * compelte the IO now.
++		 */
++		ireq->scu_status = SCU_TASK_DONE_GOOD;
++		ireq->sci_status = SCI_SUCCESS;
++		sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
++		break;
++
++	default:
++		if (d2h->fis_type == FIS_REGD2H) {
++			/* UF received change the device state to ATAPI_ERROR */
++			status = ireq->sci_status;
++			sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
++		} else {
++			/* If receiving any non-sucess TC status, no UF
++			 * received yet, then an UF for the status fis
++			 * is coming after (XXX: suspect this is
++			 * actually a protocol error or a bug like the
++			 * DONE_UNEXP_FIS case)
++			 */
++			ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
++			ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
++
++			sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
++		}
++		break;
++	}
++
++	return status;
++}
++
+ enum sci_status
+ sci_io_request_tc_completion(struct isci_request *ireq,
+ 				  u32 completion_code)
+@@ -2017,6 +2297,17 @@ sci_io_request_tc_completion(struct isci_request *ireq,
+ 		return request_aborting_state_tc_event(ireq,
+ 						       completion_code);
+ 
++	case SCI_REQ_ATAPI_WAIT_H2D:
++		return atapi_raw_completion(ireq, completion_code,
++					    SCI_REQ_ATAPI_WAIT_PIO_SETUP);
++
++	case SCI_REQ_ATAPI_WAIT_TC_COMP:
++		return atapi_raw_completion(ireq, completion_code,
++					    SCI_REQ_ATAPI_WAIT_D2H);
++
++	case SCI_REQ_ATAPI_WAIT_D2H:
++		return atapi_data_tc_completion_handler(ireq, completion_code);
++
+ 	default:
+ 		dev_warn(&ihost->pdev->dev,
+ 			 "%s: SCIC IO Request given task completion "
+@@ -2423,6 +2714,8 @@ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_
+ 	 */
+ 	if (fis->status & ATA_DF)
+ 		ts->stat = SAS_PROTO_RESPONSE;
++	else if (fis->status & ATA_ERR)
++		ts->stat = SAM_STAT_CHECK_CONDITION;
+ 	else
+ 		ts->stat = SAM_STAT_GOOD;
+ 
+@@ -2782,6 +3075,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
+ {
+ 	struct isci_request *ireq = container_of(sm, typeof(*ireq), sm);
+ 	struct domain_device *dev = ireq->target_device->domain_dev;
++	enum sci_base_request_states state;
+ 	struct sas_task *task;
+ 
+ 	/* XXX as hch said always creating an internal sas_task for tmf
+@@ -2793,26 +3087,30 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
+ 	 * substates
+ 	 */
+ 	if (!task && dev->dev_type == SAS_END_DEV) {
+-		sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP);
++		state = SCI_REQ_TASK_WAIT_TC_COMP;
+ 	} else if (!task &&
+ 		   (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high ||
+ 		    isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) {
+-		sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED);
++		state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
+ 	} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
+-		sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP);
++		state = SCI_REQ_SMP_WAIT_RESP;
+ 	} else if (task && sas_protocol_ata(task->task_proto) &&
+ 		   !task->ata_task.use_ncq) {
+-		u32 state;
+-
+-		if (task->data_dir == DMA_NONE)
++		if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
++			task->ata_task.fis.command == ATA_CMD_PACKET) {
++			state = SCI_REQ_ATAPI_WAIT_H2D;
++		} else if (task->data_dir == DMA_NONE) {
+ 			state = SCI_REQ_STP_NON_DATA_WAIT_H2D;
+-		else if (task->ata_task.dma_xfer)
++		} else if (task->ata_task.dma_xfer) {
+ 			state = SCI_REQ_STP_UDMA_WAIT_TC_COMP;
+-		else /* PIO */
++		} else /* PIO */ {
+ 			state = SCI_REQ_STP_PIO_WAIT_H2D;
+-
+-		sci_change_state(sm, state);
++		}
++	} else {
++		/* SSP or NCQ are fully accelerated, no substates */
++		return;
+ 	}
++	sci_change_state(sm, state);
+ }
+ 
+ static void sci_request_completed_state_enter(struct sci_base_state_machine *sm)
+@@ -2904,6 +3202,10 @@ static const struct sci_base_state sci_request_state_table[] = {
+ 	[SCI_REQ_TASK_WAIT_TC_RESP] = { },
+ 	[SCI_REQ_SMP_WAIT_RESP] = { },
+ 	[SCI_REQ_SMP_WAIT_TC_COMP] = { },
++	[SCI_REQ_ATAPI_WAIT_H2D] = { },
++	[SCI_REQ_ATAPI_WAIT_PIO_SETUP] = { },
++	[SCI_REQ_ATAPI_WAIT_D2H] = { },
++	[SCI_REQ_ATAPI_WAIT_TC_COMP] = { },
+ 	[SCI_REQ_COMPLETED] = {
+ 		.enter_state = sci_request_completed_state_enter,
+ 	},
+--- a/drivers/scsi/isci/request.h
++++ b/drivers/scsi/isci/request.h
+@@ -96,7 +96,6 @@ enum sci_request_protocol {
+  *	     to wait for another fis or if the transfer is complete.  Upon
+  *           receipt of a d2h fis this will be the status field of that fis.
+  * @sgl - track pio transfer progress as we iterate through the sgl
+- * @device_cdb_len - atapi device advertises it's transfer constraints at setup
+  */
+ struct isci_stp_request {
+ 	u32 pio_len;
+@@ -107,7 +106,6 @@ struct isci_stp_request {
+ 		u8 set;
+ 		u32 offset;
+ 	} sgl;
+-	u32 device_cdb_len;
+ };
+ 
+ struct isci_request {
+@@ -249,6 +247,32 @@ enum sci_base_request_states {
+ 	SCI_REQ_STP_PIO_DATA_OUT,
+ 
+ 	/*
++	 * While in this state the IO request object is waiting for the TC
++	 * completion notification for the H2D Register FIS
++	 */
++	SCI_REQ_ATAPI_WAIT_H2D,
++
++	/*
++	 * While in this state the IO request object is waiting for either a
++	 * PIO Setup.
++	 */
++	SCI_REQ_ATAPI_WAIT_PIO_SETUP,
++
++	/*
++	 * The non-data IO transit to this state in this state after receiving
++	 * TC completion. While in this state IO request object is waiting for
++	 * D2H status frame as UF.
++	 */
++	SCI_REQ_ATAPI_WAIT_D2H,
++
++	/*
++	 * When transmitting raw frames hardware reports task context completion
++	 * after every frame submission, so in the non-accelerated case we need
++	 * to expect the completion for the "cdb" frame.
++	 */
++	SCI_REQ_ATAPI_WAIT_TC_COMP,
++
++	/*
+ 	 * The AWAIT_TC_COMPLETION sub-state indicates that the started raw
+ 	 * task management request is waiting for the transmission of the
+ 	 * initial frame (i.e. command, task, etc.).
+--- a/include/scsi/libsas.h
++++ b/include/scsi/libsas.h
+@@ -389,6 +389,11 @@ sdev_to_domain_dev(struct scsi_device *sdev) {
+ 	return starget_to_domain_dev(sdev->sdev_target);
+ }
+ 
++static inline struct ata_device *sas_to_ata_dev(struct domain_device *dev)
++{
++	return &dev->sata_dev.ap->link.device[0];
++}
++
+ static inline struct domain_device *
+ cmd_to_domain_dev(struct scsi_cmnd *cmd)
+ {

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0008-SCSI-isci-SATA-STP-I-O-is-only-returned-in-the-norma.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0008-SCSI-isci-SATA-STP-I-O-is-only-returned-in-the-norma.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,52 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Wed, 28 Sep 2011 18:47:46 -0700
+Subject: [08/25] [SCSI] isci: SATA/STP I/O is only returned in the normal
+ path to libsas
+
+commit cd06b9bae18c64658d5a86526fb19cfe0ea8814f upstream.
+
+Since libsas has it's own means to escalate SATA/STP device error
+handling depending on task status codes, return all SATA/STP I/O
+on the normal path.
+
+i.e. skip sas_task_abort() and let sas_ata_task_done() disposition the
+qc.  Longer term we want to audit non-essential calls to
+sas_task_abort().
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/task.h |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
+index 4a7fa90..15b18d1 100644
+--- a/drivers/scsi/isci/task.h
++++ b/drivers/scsi/isci/task.h
+@@ -286,6 +286,25 @@ isci_task_set_completion_status(
+ 	task->task_status.resp = response;
+ 	task->task_status.stat = status;
+ 
++	switch (task->task_proto) {
++
++	case SAS_PROTOCOL_SATA:
++	case SAS_PROTOCOL_STP:
++	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
++
++		if (task_notification_selection
++		    == isci_perform_error_io_completion) {
++			/* SATA/STP I/O has it's own means of scheduling device
++			* error handling on the normal path.
++			*/
++			task_notification_selection
++				= isci_perform_normal_io_completion;
++		}
++		break;
++	default:
++		break;
++	}
++
+ 	switch (task_notification_selection) {
+ 
+ 	case isci_perform_error_io_completion:

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0009-SCSI-isci-fix-decode-of-DONE_CRC_ERR-TC-completion-s.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0009-SCSI-isci-fix-decode-of-DONE_CRC_ERR-TC-completion-s.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,33 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Wed, 28 Sep 2011 18:47:51 -0700
+Subject: [09/25] [SCSI] isci: fix decode of DONE_CRC_ERR TC completion status
+
+commit 7582ba8bdf5a119221ef663a327932cfc62bed79 upstream.
+
+DONE_CRC_ERR is not a RNC suspension condition, so do not change the
+state to expect the incoming suspension notification.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+[djbw: dropped DONE_CMD_LL_R_ERR change]
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/request.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
+index 23a5504..565a9f0 100644
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -2074,10 +2074,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
+ 	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
+ 	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
+ 	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
+-	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
+ 		sci_remote_device_suspend(ireq->target_device,
+ 			SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
+-	/* Fall through to the default case */
++		/* Fall through to the default case */
+ 	default:
+ 		/* All other completion status cause the IO to be complete. */
+ 		ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0010-SCSI-isci-The-port-state-should-be-set-to-stopping-o.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0010-SCSI-isci-The-port-state-should-be-set-to-stopping-o.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,32 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Wed, 28 Sep 2011 18:47:56 -0700
+Subject: [10/25] [SCSI] isci: The port state should be set to stopping on the
+ last phy.
+
+commit cdd05f05b4adefccfa9fce7d0e10c50f38f8a4bd upstream.
+
+Fixes a bug where any phy removed from the port set the port
+state to "stopping" - do this only when the last phy removed
+from the port.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/port.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
+index 8f6f9b7..8e59c88 100644
+--- a/drivers/scsi/isci/port.c
++++ b/drivers/scsi/isci/port.c
+@@ -294,8 +294,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
+ 					__func__, isci_device);
+ 				set_bit(IDEV_GONE, &isci_device->flags);
+ 			}
++			isci_port_change_state(isci_port, isci_stopping);
+ 		}
+-		isci_port_change_state(isci_port, isci_stopping);
+ 	}
+ 
+ 	/* Notify libsas of the borken link, this will trigger calls to our

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0012-SCSI-isci-Lookup-device-references-through-requests-.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0012-SCSI-isci-Lookup-device-references-through-requests-.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,114 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:04:50 -0700
+Subject: [12/25] [SCSI] isci: Lookup device references through requests in
+ completions.
+
+commit 0e2e27990e2dcd415f7974e8460a2f05accdddfb upstream.
+
+The LLDD needs to obtain a reference to the device through the request
+itself and not through the domain_device, because the
+domain_device.lldd_dev is set to NULL early in the lldd_dev_gone call.
+This relies on the fact that the isci_remote_device object is keeping a
+seperate reference count of outstanding requests.  TODO: unify the
+request count tracking with the isci_remote_device kref.
+
+The failure signature of this condition looks like the following
+log, where the important bits are the call to lldd_dev_gone followed
+by a crash in isci_terminate_request_core:
+
+[  229.151541] isci 0000:0b:00.0: isci_remote_device_gone: domain_device = ffff8801492d4800, isci_device = ffff880143c657d0, isci_port = ffff880143c63658
+[  229.166007] isci 0000:0b:00.0: isci_remote_device_stop: isci_device = ffff880143c657d0
+[  229.175317] isci 0000:0b:00.0: isci_terminate_pending_requests: idev=ffff880143c657d0 request=ffff88014741f000; task=ffff8801470f46c0 old_state=2
+[  229.189702] isci 0000:0b:00.0: isci_terminate_request_core: device = ffff880143c657d0; request = ffff88014741f000
+[  229.201339] isci 0000:0b:00.0: isci_terminate_request_core: before completion wait (ffff88014741f000/ffff880149715ad0)
+[  229.213414] isci 0000:0b:00.0: sci_controller_process_completions: completion queue entry:0x8000a0e9
+[  229.214401] BUG: unable to handle kernel NULL pointer dereference at 0000000000000228
+[  229.214401] IP:jdskirvi-testlbo [<ffffffffa00a58be>] sci_request_completed_state_enter+0x50/0xafb [isci]
+[  229.214401] PGD 13d19e067 PUD 13d104067 PMD 0
+[  229.214401] Oops: 0000 [#1] SMP
+[  229.214401] CPU 0 x kernel: [  226
+[  229.214401] Modules linked in: ipv6 dm_multipath uinput nouveau snd_hda_codec_realtek snd_hda_intel ttm drm_kms_helper drm snd_hda_codec snd_hwdep snd_pcm snd_timer i2c_algo_bit isci snd libsas ioatdma mxm_wmi iTCO_wdt soundcore snd_page_alloc scsi_transport_sas iTCO_vendor_support wmi dca video i2c_i801 i2c_core [last unloaded: speedstep_lib]
+[  229.214401]
+[  229.214401] Pid: 5, comm: kworker/u:0 Not tainted 3.0.0-isci-11.7.29+ #30.353196] Buffer  Intel Corporation Stoakley/Pearlcity Workstation
+[  229.214401] RIP: 0010:[<ffffffffa00a58be>] I/O error on dev [<ffffffffa00a58be>] sci_request_completed_state_enter+0x50/0xafb [isci]
+[  229.214401] RSP: 0018:ffff88014fc03d20  EFLAGS: 00010046
+[  229.214401] RAX: 0000000000000000 RBX: ffff88014741f000 RCX: 0000000000000000
+[  229.214401] RDX: ffffffffa00b2c90 RSI: 0000000000000017 RDI: ffff88014741f0a0
+[  229.214401] RBP: ffff88014fc03d90 R08: 0000000000000018 R09: 0000000000000000
+[  229.214401] R10: 0000000000000000 R11: ffffffff81a17d98 R12: 000000000000001d
+[  229.214401] R13: ffff8801470f46c0 R14: 0000000000000000 R15: 0000000000008000
+[  229.214401] FS:  0000000000000000(0000) GS:ffff88014fc00000(0000) knlGS:0000000000000000
+[  229.214401] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+[  229.214401] CR2: 0000000000000228 CR3: 000000013ceaa000 CR4: 00000000000406f0
+[  229.214401] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[  229.214401] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+[  229.214401] Process kworker/u:0 (pid: 5, threadinfo ffff880149714000, task ffff880149718000)
+[  229.214401] Call Trace:
+[  229.214401]  <IRQ>
+[  229.214401]  [<ffffffffa00aa6ce>] sci_change_state+0x4a/0x4f [isci]
+[  229.214401]  [<ffffffffa00a4ca6>] sci_io_request_tc_completion+0x79c/0x7a0 [isci]
+[  229.214401]  [<ffffffffa00acf35>] sci_controller_process_completions+0x14f/0x396 [isci]
+[  229.214401]  [<ffffffffa00abbda>] ? spin_lock_irq+0xe/0x10 [isci]
+[  229.214401]  [<ffffffffa00ad2cf>] isci_host_completion_routine+0x71/0x2be [isci]
+[  229.214401]  [<ffffffff8107c6b3>] ? mark_held_locks+0x52/0x70
+[  229.214401]  [<ffffffff810538e8>] tasklet_action+0x90/0xf1
+[  229.214401]  [<ffffffff81054050>] __do_softirq+0xe5/0x1bf
+[  229.214401]  [<ffffffff8106d9d1>] ? hrtimer_interrupt+0x129/0x1bb
+[  229.214401]  [<ffffffff814ff69c>] call_softirq+0x1c/0x30
+[  229.214401]  [<ffffffff8100bb67>] do_softirq+0x4b/0xa3
+[  229.214401]  [<ffffffff81053d84>] irq_exit+0x53/0xb4
+[  229.214401]  [<ffffffff814fffe7>] smp_apic_timer_interrupt+0x83/0x91
+[  229.214401]  [<ffffffff814fee53>] apic_timer_interrupt+0x13/0x20
+[  229.214401]  <EOI>
+[  229.214401]  [<ffffffff814f7ad4>] ? retint_restore_args+0x13/0x13
+[  229.214401]  [<ffffffff8107af29>] ? trace_hardirqs_off+0xd/0xf
+[  229.214401]  [<ffffffff8104ea71>] ? vprintk+0x40b/0x452
+[  229.214401]  [<ffffffff814f4b5a>] printk+0x41/0x47
+[  229.214401]  [<ffffffff81314484>] __dev_printk+0x78/0x7a
+[  229.214401]  [<ffffffff8131471e>] dev_printk+0x45/0x47
+[  229.214401]  [<ffffffffa00ae2a3>] isci_terminate_request_core+0x15d/0x317 [isci]
+[  229.214401]  [<ffffffffa00af1ad>] isci_terminate_pending_requests+0x1a4/0x204 [isci]
+[  229.214401]  [<ffffffffa00229f6>] ? sas_phye_oob_error+0xc3/0xc3 [libsas]
+[  229.214401]  [<ffffffffa00a7d9e>] isci_remote_device_nuke_requests+0xa6/0xff [isci]
+[  229.214401]  [<ffffffffa00a811a>] isci_remote_device_stop+0x7c/0x166 [isci]
+[  229.214401]  [<ffffffffa00229f6>] ? sas_phye_oob_error+0xc3/0xc3 [libsas]
+[  229.214401]  [<ffffffffa00a827a>] isci_remote_device_gone+0x76/0x7e [isci]
+[  229.214401]  [<ffffffffa002363e>] sas_notify_lldd_dev_gone+0x34/0x36 [libsas]
+[  229.214401]  [<ffffffffa0023945>] sas_unregister_dev+0x57/0x9c [libsas]
+[  229.214401]  [<ffffffffa00239c0>] sas_unregister_domain_devices+0x36/0x65 [libsas]
+[  229.214401]  [<ffffffffa0022cb8>] sas_deform_port+0x72/0x1ac [libsas]
+[  229.214401]  [<ffffffffa00229f6>] ? sas_phye_oob_error+0xc3/0xc3 [libsas]
+[  229.214401]  [<ffffffffa0022a34>] sas_phye_loss_of_signal+0x3e/0x42 [libsas]
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/request.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
+index 565a9f0..bfc7379 100644
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -2728,9 +2728,9 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
+ 	struct sas_task *task = isci_request_access_task(request);
+ 	struct ssp_response_iu *resp_iu;
+ 	unsigned long task_flags;
+-	struct isci_remote_device *idev = isci_lookup_device(task->dev);
+-	enum service_response response       = SAS_TASK_UNDELIVERED;
+-	enum exec_status status         = SAS_ABORTED_TASK;
++	struct isci_remote_device *idev = request->target_device;
++	enum service_response response = SAS_TASK_UNDELIVERED;
++	enum exec_status status = SAS_ABORTED_TASK;
+ 	enum isci_request_status request_status;
+ 	enum isci_completion_selection complete_to_host
+ 		= isci_perform_normal_io_completion;
+@@ -3061,7 +3061,6 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
+ 
+ 	/* complete the io request to the core. */
+ 	sci_controller_complete_io(ihost, request->target_device, request);
+-	isci_put_device(idev);
+ 
+ 	/* set terminated handle so it cannot be completed or
+ 	 * terminated again, and to cause any calls into abort

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0013-SCSI-isci-Immediately-fail-I-O-to-removed-devices.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0013-SCSI-isci-Immediately-fail-I-O-to-removed-devices.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,58 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:04:56 -0700
+Subject: [13/25] [SCSI] isci: Immediately fail I/O to removed devices.
+
+commit c2cb8a5fd7d5d8729a4fc25937c4d6564f9a7aa3 upstream.
+
+In the case where an I/O fails to start in isci_request_execute,
+only allow retries if the device is not already gone.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/task.c |   31 +++++++++++++++++++++----------
+ 1 file changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index e2d9418..e8cf17b 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -212,16 +212,27 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
+ 					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_refuse(ihost, task,
+-							 SAS_TASK_COMPLETE,
+-							 SAS_QUEUE_FULL);
++					if (test_bit(IDEV_GONE, &idev->flags)) {
++
++						/* Indicate that the device
++						 * is gone.
++						 */
++						isci_task_refuse(ihost, task,
++							SAS_TASK_UNDELIVERED,
++							SAS_DEVICE_UNKNOWN);
++					} 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_refuse(ihost, task,
++							SAS_TASK_COMPLETE,
++							SAS_QUEUE_FULL);
++					}
+ 				}
+ 			}
+ 		}

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0014-SCSI-isci-Fix-tag-leak-in-tasks-and-terminated-reque.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0014-SCSI-isci-Fix-tag-leak-in-tasks-and-terminated-reque.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,103 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:01 -0700
+Subject: [14/25] [SCSI] isci: Fix tag leak in tasks and terminated requests.
+
+commit d6891682220c18c01bf6838f30e37342c38fde44 upstream.
+
+Make sure terminated requests and completed task tags are freed.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/task.c |   51 ++++++++++++++++++++++++++++------------------
+ 1 file changed, 31 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index e8cf17b..7180b04 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -552,11 +552,27 @@ static void isci_request_cleanup_completed_loiterer(
+ 
+ 	if (isci_request != NULL) {
+ 		spin_lock_irqsave(&isci_host->scic_lock, flags);
++		isci_free_tag(isci_host, isci_request->io_tag);
++		isci_request_change_state(isci_request, unallocated);
+ 		list_del_init(&isci_request->dev_node);
+ 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ 	}
+ }
+ 
++static int isci_request_is_dealloc_managed(enum isci_request_status stat)
++{
++	switch (stat) {
++	case aborted:
++	case aborting:
++	case terminating:
++	case completed:
++	case dead:
++		return true;
++	default:
++		return false;
++	}
++}
++
+ /**
+  * isci_terminate_request_core() - This function will terminate the given
+  *    request, and wait for it to complete.  This function must only be called
+@@ -574,7 +590,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 	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     termination_completed = 1;
+ 	struct completion *io_request_completion;
+@@ -702,23 +717,11 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 			 * needs to be detached and freed here.
+ 			 */
+ 			spin_lock_irqsave(&isci_request->state_lock, flags);
+-			request_status = isci_request->status;
+-
+-			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;
+-			}
++
++			needs_cleanup_handling
++				= isci_request_is_dealloc_managed(
++					isci_request->status);
++
+ 			spin_unlock_irqrestore(&isci_request->state_lock, flags);
+ 
+ 		}
+@@ -1329,8 +1332,16 @@ isci_task_request_complete(struct isci_host *ihost,
+ 	 */
+ 	set_bit(IREQ_TERMINATED, &ireq->flags);
+ 
+-	isci_request_change_state(ireq, unallocated);
+-	list_del_init(&ireq->dev_node);
++	/* As soon as something is in the terminate path, deallocation is
++	 * managed there.  Note that the final non-managed state of a task
++	 * request is "completed".
++	 */
++	if ((ireq->status == completed) ||
++	    !isci_request_is_dealloc_managed(ireq->status)) {
++		isci_request_change_state(ireq, unallocated);
++		isci_free_tag(ihost, ireq->io_tag);
++		list_del_init(&ireq->dev_node);
++	}
+ 
+ 	/* The task management part completes last. */
+ 	complete(tmf_complete);

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0015-SCSI-isci-Handle-task-request-timeouts-correctly.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0015-SCSI-isci-Handle-task-request-timeouts-correctly.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,260 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:06 -0700
+Subject: [15/25] [SCSI] isci: Handle task request timeouts correctly.
+
+commit b343dff1a269bcc0eac123ef541c5476b03d52c1 upstream.
+
+In the case where "task" requests timeout (note that this class of
+requests can also include SATA/STP soft reset FIS transmissions),
+handle the case where the task was being managed by some call to
+terminate the task request by completing both the tmf and the aborting
+process.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/task.c |  149 +++++++++++++++++++++++++++++++++-------------
+ drivers/scsi/isci/task.h |    2 +
+ 2 files changed, 109 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index 7180b04..4175f17 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -338,6 +338,61 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
+ 	return ireq;
+ }
+ 
++/**
++* isci_request_mark_zombie() - This function must be called with scic_lock held.
++*/
++static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_request *ireq)
++{
++	struct completion *tmf_completion = NULL;
++	struct completion *req_completion;
++
++	/* Set the request state to "dead". */
++	ireq->status = dead;
++
++	req_completion = ireq->io_request_completion;
++	ireq->io_request_completion = NULL;
++
++	if (ireq->ttype == io_task) {
++
++		/* Break links with the sas_task - the callback is done
++		 * elsewhere.
++		 */
++		struct sas_task *task = isci_request_access_task(ireq);
++
++		if (task)
++			task->lldd_task = NULL;
++
++		ireq->ttype_ptr.io_task_ptr = NULL;
++	} else {
++		/* Break links with the TMF request. */
++		struct isci_tmf *tmf = isci_request_access_tmf(ireq);
++
++		/* In the case where a task request is dying,
++		 * the thread waiting on the complete will sit and
++		 * timeout unless we wake it now.  Since the TMF
++		 * has a default error status, complete it here
++		 * to wake the waiting thread.
++		 */
++		if (tmf) {
++			tmf_completion = tmf->complete;
++			tmf->complete = NULL;
++		}
++		ireq->ttype_ptr.tmf_task_ptr = NULL;
++		dev_dbg(&ihost->pdev->dev, "%s: tmf_code %d, managed tag %#x\n",
++			__func__, tmf->tmf_code, tmf->io_tag);
++	}
++
++	dev_warn(&ihost->pdev->dev, "task context unrecoverable (tag: %#x)\n",
++		 ireq->io_tag);
++
++	/* Don't force waiting threads to timeout. */
++	if (req_completion)
++		complete(req_completion);
++
++	if (tmf_completion != NULL)
++		complete(tmf_completion);
++}
++
+ static int isci_task_execute_tmf(struct isci_host *ihost,
+ 				 struct isci_remote_device *idev,
+ 				 struct isci_tmf *tmf, unsigned long timeout_ms)
+@@ -375,6 +430,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
+ 
+ 	/* Assign the pointer to the TMF's completion kernel wait structure. */
+ 	tmf->complete = &completion;
++	tmf->status = SCI_FAILURE_TIMEOUT;
+ 
+ 	ireq = isci_task_request_build(ihost, idev, tag, tmf);
+ 	if (!ireq)
+@@ -410,18 +466,35 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
+ 					       msecs_to_jiffies(timeout_ms));
+ 
+ 	if (timeleft == 0) {
++		/* The TMF did not complete - this could be because
++		 * of an unplug.  Terminate the TMF request now.
++		 */
+ 		spin_lock_irqsave(&ihost->scic_lock, flags);
+ 
+ 		if (tmf->cb_state_func != NULL)
+-			tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data);
++			tmf->cb_state_func(isci_tmf_timed_out, tmf,
++					   tmf->cb_data);
+ 
+-		sci_controller_terminate_request(ihost,
+-						  idev,
+-						  ireq);
++		sci_controller_terminate_request(ihost, idev, ireq);
+ 
+ 		spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ 
+-		wait_for_completion(tmf->complete);
++		timeleft = wait_for_completion_timeout(
++			&completion,
++			msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
++
++		if (!timeleft) {
++			/* Strange condition - the termination of the TMF
++			 * request timed-out.
++			 */
++			spin_lock_irqsave(&ihost->scic_lock, flags);
++
++			/* If the TMF status has not changed, kill it. */
++			if (tmf->status == SCI_FAILURE_TIMEOUT)
++				isci_request_mark_zombie(ihost, ireq);
++
++			spin_unlock_irqrestore(&ihost->scic_lock, flags);
++		}
+ 	}
+ 
+ 	isci_print_tmf(tmf);
+@@ -645,42 +718,27 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 				__func__, isci_request, io_request_completion);
+ 
+ 			/* Wait here for the request to complete. */
+-			#define TERMINATION_TIMEOUT_MSEC 500
+ 			termination_completed
+ 				= wait_for_completion_timeout(
+ 				   io_request_completion,
+-				   msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
++				   msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
+ 
+ 			if (!termination_completed) {
+ 
+ 				/* The request to terminate has timed out.  */
+-				spin_lock_irqsave(&ihost->scic_lock,
+-						  flags);
++				spin_lock_irqsave(&ihost->scic_lock, flags);
+ 
+ 				/* Check for state changes. */
+-				if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) {
++				if (!test_bit(IREQ_TERMINATED,
++					      &isci_request->flags)) {
+ 
+ 					/* The best we can do is to have the
+ 					 * request die a silent death if it
+ 					 * ever really completes.
+-					 *
+-					 * Set the request state to "dead",
+-					 * and clear the task pointer so that
+-					 * an actual completion event callback
+-					 * doesn't do anything.
+ 					 */
+-					isci_request->status = dead;
+-					isci_request->io_request_completion
+-						= NULL;
+-
+-					if (isci_request->ttype == io_task) {
+-
+-						/* Break links with the
+-						* sas_task.
+-						*/
+-						isci_request->ttype_ptr.io_task_ptr
+-							= NULL;
+-					}
++					isci_request_mark_zombie(ihost,
++								 isci_request);
++					needs_cleanup_handling = true;
+ 				} else
+ 					termination_completed = 1;
+ 
+@@ -1302,7 +1360,8 @@ isci_task_request_complete(struct isci_host *ihost,
+ 			   enum sci_task_status completion_status)
+ {
+ 	struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+-	struct completion *tmf_complete;
++	struct completion *tmf_complete = NULL;
++	struct completion *request_complete = ireq->io_request_completion;
+ 
+ 	dev_dbg(&ihost->pdev->dev,
+ 		"%s: request = %p, status=%d\n",
+@@ -1310,22 +1369,23 @@ isci_task_request_complete(struct isci_host *ihost,
+ 
+ 	isci_request_change_state(ireq, completed);
+ 
+-	tmf->status = completion_status;
+ 	set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
+ 
+-	if (tmf->proto == SAS_PROTOCOL_SSP) {
+-		memcpy(&tmf->resp.resp_iu,
+-		       &ireq->ssp.rsp,
+-		       SSP_RESP_IU_MAX_SIZE);
+-	} else if (tmf->proto == SAS_PROTOCOL_SATA) {
+-		memcpy(&tmf->resp.d2h_fis,
+-		       &ireq->stp.rsp,
+-		       sizeof(struct dev_to_host_fis));
++	if (tmf) {
++		tmf->status = completion_status;
++
++		if (tmf->proto == SAS_PROTOCOL_SSP) {
++			memcpy(&tmf->resp.resp_iu,
++			       &ireq->ssp.rsp,
++			       SSP_RESP_IU_MAX_SIZE);
++		} else if (tmf->proto == SAS_PROTOCOL_SATA) {
++			memcpy(&tmf->resp.d2h_fis,
++			       &ireq->stp.rsp,
++			       sizeof(struct dev_to_host_fis));
++		}
++		/* PRINT_TMF( ((struct isci_tmf *)request->task)); */
++		tmf_complete = tmf->complete;
+ 	}
+-
+-	/* PRINT_TMF( ((struct isci_tmf *)request->task)); */
+-	tmf_complete = tmf->complete;
+-
+ 	sci_controller_complete_io(ihost, ireq->target_device, ireq);
+ 	/* set the 'terminated' flag handle to make sure it cannot be terminated
+ 	 *  or completed again.
+@@ -1343,8 +1403,13 @@ isci_task_request_complete(struct isci_host *ihost,
+ 		list_del_init(&ireq->dev_node);
+ 	}
+ 
++	/* "request_complete" is set if the task was being terminated. */
++	if (request_complete)
++		complete(request_complete);
++
+ 	/* The task management part completes last. */
+-	complete(tmf_complete);
++	if (tmf_complete)
++		complete(tmf_complete);
+ }
+ 
+ static void isci_smp_task_timedout(unsigned long _task)
+diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
+index 15b18d1..c9ccd0b 100644
+--- a/drivers/scsi/isci/task.h
++++ b/drivers/scsi/isci/task.h
+@@ -58,6 +58,8 @@
+ #include <scsi/sas_ata.h>
+ #include "host.h"
+ 
++#define ISCI_TERMINATION_TIMEOUT_MSEC 500
++
+ struct isci_request;
+ 
+ /**

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0016-SCSI-isci-No-task_done-callbacks-in-error-handler-pa.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0016-SCSI-isci-No-task_done-callbacks-in-error-handler-pa.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,117 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:11 -0700
+Subject: [16/25] [SCSI] isci: No task_done callbacks in error handler paths.
+
+commit db49c2d037d50dfc67b29a4e013d6250ca97c3aa upstream.
+
+libsas will cleanup pending sas_tasks after error handler
+path functions are called; do not call task_done callbacks.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/task.c |   69 ++++++++++------------------------------------
+ 1 file changed, 14 insertions(+), 55 deletions(-)
+
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index 4175f17..c1f439b 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -585,53 +585,6 @@ static enum isci_request_status isci_task_validate_request_to_abort(
+ 	return old_state;
+ }
+ 
+-/**
+-* isci_request_cleanup_completed_loiterer() - This function will take care of
+-*    the final cleanup on any request which has been explicitly terminated.
+-* @isci_host: This parameter specifies the ISCI host object
+-* @isci_device: This is the device to which the request is pending.
+-* @isci_request: This parameter specifies the terminated request object.
+-* @task: This parameter is the libsas I/O request.
+-*/
+-static void isci_request_cleanup_completed_loiterer(
+-	struct isci_host          *isci_host,
+-	struct isci_remote_device *isci_device,
+-	struct isci_request       *isci_request,
+-	struct sas_task           *task)
+-{
+-	unsigned long flags;
+-
+-	dev_dbg(&isci_host->pdev->dev,
+-		"%s: isci_device=%p, request=%p, task=%p\n",
+-		__func__, isci_device, isci_request, task);
+-
+-	if (task != NULL) {
+-
+-		spin_lock_irqsave(&task->task_state_lock, flags);
+-		task->lldd_task = NULL;
+-
+-		task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+-
+-		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);
+-	}
+-
+-	if (isci_request != NULL) {
+-		spin_lock_irqsave(&isci_host->scic_lock, flags);
+-		isci_free_tag(isci_host, isci_request->io_tag);
+-		isci_request_change_state(isci_request, unallocated);
+-		list_del_init(&isci_request->dev_node);
+-		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+-	}
+-}
+-
+ static int isci_request_is_dealloc_managed(enum isci_request_status stat)
+ {
+ 	switch (stat) {
+@@ -666,7 +619,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 	unsigned long     flags;
+ 	unsigned long     termination_completed = 1;
+ 	struct completion *io_request_completion;
+-	struct sas_task   *task;
+ 
+ 	dev_dbg(&ihost->pdev->dev,
+ 		"%s: device = %p; request = %p\n",
+@@ -676,10 +628,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 
+ 	io_request_completion = isci_request->io_request_completion;
+ 
+-	task = (isci_request->ttype == io_task)
+-		? isci_request_access_task(isci_request)
+-		: NULL;
+-
+ 	/* Note that we are not going to control
+ 	 * the target to abort the request.
+ 	 */
+@@ -783,9 +731,20 @@ static void isci_terminate_request_core(struct isci_host *ihost,
+ 			spin_unlock_irqrestore(&isci_request->state_lock, flags);
+ 
+ 		}
+-		if (needs_cleanup_handling)
+-			isci_request_cleanup_completed_loiterer(
+-				ihost, idev, isci_request, task);
++		if (needs_cleanup_handling) {
++
++			dev_dbg(&ihost->pdev->dev,
++				"%s: cleanup isci_device=%p, request=%p\n",
++				__func__, idev, isci_request);
++
++			if (isci_request != NULL) {
++				spin_lock_irqsave(&ihost->scic_lock, flags);
++				isci_free_tag(ihost, isci_request->io_tag);
++				isci_request_change_state(isci_request, unallocated);
++				list_del_init(&isci_request->dev_node);
++				spin_unlock_irqrestore(&ihost->scic_lock, flags);
++			}
++		}
+ 	}
+ }
+ 

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0017-SCSI-isci-Fix-task-management-for-SMP-SATA-and-on-de.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0017-SCSI-isci-Fix-task-management-for-SMP-SATA-and-on-de.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,381 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:16 -0700
+Subject: [17/25] [SCSI] isci: Fix task management for SMP, SATA and on dev
+ remove.
+
+commit 98145cb722b51ccc3ba27166c9803545accba950 upstream.
+
+libsas uses the LLDD abort task interface to handle I/O timeouts
+in the SATA/STP and SMP discovery paths, so this change will terminate
+STP/SMP requests. Also, if the device is gone, the lldd will prevent
+libsas from further escalations in the error handler.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/remote_device.c |   47 -----------
+ drivers/scsi/isci/remote_device.h |    2 -
+ drivers/scsi/isci/task.c          |  169 ++++++++++++++-----------------------
+ drivers/scsi/isci/task.h          |   33 +-------
+ 4 files changed, 67 insertions(+), 184 deletions(-)
+
+diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
+index fbf9ce2..20c77ed 100644
+--- a/drivers/scsi/isci/remote_device.c
++++ b/drivers/scsi/isci/remote_device.c
+@@ -1438,53 +1438,6 @@ int isci_remote_device_found(struct domain_device *domain_dev)
+ 
+ 	return status == SCI_SUCCESS ? 0 : -ENODEV;
+ }
+-/**
+- * isci_device_is_reset_pending() - This function will check if there is any
+- *    pending reset condition on the device.
+- * @request: This parameter is the isci_device object.
+- *
+- * true if there is a reset pending for the device.
+- */
+-bool isci_device_is_reset_pending(
+-	struct isci_host *isci_host,
+-	struct isci_remote_device *isci_device)
+-{
+-	struct isci_request *isci_request;
+-	struct isci_request *tmp_req;
+-	bool reset_is_pending = false;
+-	unsigned long flags;
+-
+-	dev_dbg(&isci_host->pdev->dev,
+-		"%s: isci_device = %p\n", __func__, isci_device);
+-
+-	spin_lock_irqsave(&isci_host->scic_lock, flags);
+-
+-	/* Check for reset on all pending requests. */
+-	list_for_each_entry_safe(isci_request, tmp_req,
+-				 &isci_device->reqs_in_process, dev_node) {
+-		dev_dbg(&isci_host->pdev->dev,
+-			"%s: isci_device = %p request = %p\n",
+-			__func__, isci_device, isci_request);
+-
+-		if (isci_request->ttype == io_task) {
+-			struct sas_task *task = isci_request_access_task(
+-				isci_request);
+-
+-			spin_lock(&task->task_state_lock);
+-			if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
+-				reset_is_pending = true;
+-			spin_unlock(&task->task_state_lock);
+-		}
+-	}
+-
+-	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+-
+-	dev_dbg(&isci_host->pdev->dev,
+-		"%s: isci_device = %p reset_is_pending = %d\n",
+-		__func__, isci_device, reset_is_pending);
+-
+-	return reset_is_pending;
+-}
+ 
+ /**
+  * isci_device_clear_reset_pending() - This function will clear if any pending
+diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
+index e1747ea..bee6dd2 100644
+--- a/drivers/scsi/isci/remote_device.h
++++ b/drivers/scsi/isci/remote_device.h
+@@ -132,8 +132,6 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost,
+ 				      struct isci_remote_device *idev);
+ void isci_remote_device_gone(struct domain_device *domain_dev);
+ int isci_remote_device_found(struct domain_device *domain_dev);
+-bool isci_device_is_reset_pending(struct isci_host *ihost,
+-				  struct isci_remote_device *idev);
+ void isci_device_clear_reset_pending(struct isci_host *ihost,
+ 				     struct isci_remote_device *idev);
+ /**
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index c1f439b..ec85beb 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -920,22 +920,14 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun)
+ 		"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
+ 		 __func__, domain_device, isci_host, isci_device);
+ 
+-	if (isci_device)
+-		set_bit(IDEV_EH, &isci_device->flags);
++	if (!isci_device) {
++		/* If the device is gone, stop the escalations. */
++		dev_dbg(&isci_host->pdev->dev, "%s: No dev\n", __func__);
+ 
+-	/* If there is a device reset pending on any request in the
+-	 * device's list, fail this LUN reset request in order to
+-	 * escalate to the device reset.
+-	 */
+-	if (!isci_device ||
+-	    isci_device_is_reset_pending(isci_host, isci_device)) {
+-		dev_dbg(&isci_host->pdev->dev,
+-			 "%s: No dev (%p), or "
+-			 "RESET PENDING: domain_device=%p\n",
+-			 __func__, isci_device, domain_device);
+-		ret = TMF_RESP_FUNC_FAILED;
++		ret = TMF_RESP_FUNC_COMPLETE;
+ 		goto out;
+ 	}
++	set_bit(IDEV_EH, &isci_device->flags);
+ 
+ 	/* Send the task management part of the reset. */
+ 	if (sas_protocol_ata(domain_device->tproto)) {
+@@ -1044,7 +1036,7 @@ int isci_task_abort_task(struct sas_task *task)
+ 	struct isci_tmf           tmf;
+ 	int                       ret = TMF_RESP_FUNC_FAILED;
+ 	unsigned long             flags;
+-	bool                      any_dev_reset = false;
++	int                       perform_termination = 0;
+ 
+ 	/* Get the isci_request reference from the task.  Note that
+ 	 * this check does not depend on the pending request list
+@@ -1066,89 +1058,34 @@ int isci_task_abort_task(struct sas_task *task)
+ 	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ 
+ 	dev_dbg(&isci_host->pdev->dev,
+-		"%s: task = %p\n", __func__, task);
+-
+-	if (!isci_device || !old_request)
+-		goto out;
++		"%s: dev = %p, task = %p, old_request == %p\n",
++		__func__, isci_device, task, old_request);
+ 
+-	set_bit(IDEV_EH, &isci_device->flags);
+-
+-	/* 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
+-	 */
+-	if (sas_protocol_ata(task->task_proto)) {
+-		dev_dbg(&isci_host->pdev->dev,
+-			    " task %p is for a STP/SATA device;"
+-			    " returning TMF_RESP_FUNC_FAILED\n"
+-			    " to cause a LUN reset...\n", task);
+-		goto out;
+-	}
+-
+-	dev_dbg(&isci_host->pdev->dev,
+-		"%s: old_request == %p\n", __func__, old_request);
+-
+-	any_dev_reset = isci_device_is_reset_pending(isci_host, isci_device);
+-
+-	spin_lock_irqsave(&task->task_state_lock, flags);
+-
+-	any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET);
++	if (isci_device)
++		set_bit(IDEV_EH, &isci_device->flags);
+ 
+-	/* 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).
++	/* Device reset conditions signalled in task_state_flags are the
++	 * responsbility of libsas to observe at the start of the error
++	 * handler thread.
+ 	 */
+-	if ((old_request == NULL) || any_dev_reset) {
+-
+-		/* If the device reset task flag is set, fail the task
+-		 * management request.  Otherwise, the original request
+-		 * has completed.
+-		 */
+-		if (any_dev_reset) {
+-
+-			/* Turn off the task's DONE to make sure this
+-			 * task is escalated to a target reset.
+-			 */
+-			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.
+-			 */
+-			ret = TMF_RESP_FUNC_FAILED;
+-
+-			dev_dbg(&isci_host->pdev->dev,
+-				"%s: Failing task abort in order to "
+-				"escalate to target reset because\n"
+-				"SAS_TASK_NEED_DEV_RESET is set for "
+-				"task %p on dev %p\n",
+-				__func__, task, isci_device);
+-
+-
+-		} 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
+-			 * was sucessful.
+-			 */
+-			isci_set_task_doneflags(task);
+-
+-			spin_unlock_irqrestore(&task->task_state_lock, flags);
++	if (!isci_device || !old_request) {
++		/* 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
++		* was sucessful.
++		*/
++		spin_lock_irqsave(&task->task_state_lock, flags);
++		task->task_state_flags |= SAS_TASK_STATE_DONE;
++		task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
++					    SAS_TASK_STATE_PENDING);
++		spin_unlock_irqrestore(&task->task_state_lock, flags);
+ 
+-			ret = TMF_RESP_FUNC_COMPLETE;
++		ret = TMF_RESP_FUNC_COMPLETE;
+ 
+-			dev_dbg(&isci_host->pdev->dev,
+-				"%s: abort task not needed for %p\n",
+-				__func__, task);
+-		}
++		dev_dbg(&isci_host->pdev->dev,
++			"%s: abort task not needed for %p\n",
++			__func__, task);
+ 		goto out;
+-	} else {
+-		spin_unlock_irqrestore(&task->task_state_lock, flags);
+ 	}
+ 
+ 	spin_lock_irqsave(&isci_host->scic_lock, flags);
+@@ -1177,24 +1114,44 @@ int isci_task_abort_task(struct sas_task *task)
+ 		goto out;
+ 	}
+ 	if (task->task_proto == SAS_PROTOCOL_SMP ||
++	    sas_protocol_ata(task->task_proto) ||
+ 	    test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
+ 
+ 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ 
+ 		dev_dbg(&isci_host->pdev->dev,
+-			"%s: SMP request (%d)"
++			"%s: %s request"
+ 			" or complete_in_target (%d), thus no TMF\n",
+-			__func__, (task->task_proto == SAS_PROTOCOL_SMP),
++			__func__,
++			((task->task_proto == SAS_PROTOCOL_SMP)
++				? "SMP"
++				: (sas_protocol_ata(task->task_proto)
++					? "SATA/STP"
++					: "<other>")
++			 ),
+ 			test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags));
+ 
+-		/* Set the state on the task. */
+-		isci_task_all_done(task);
+-
+-		ret = TMF_RESP_FUNC_COMPLETE;
++		if (test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
++			spin_lock_irqsave(&task->task_state_lock, flags);
++			task->task_state_flags |= SAS_TASK_STATE_DONE;
++			task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
++						    SAS_TASK_STATE_PENDING);
++			spin_unlock_irqrestore(&task->task_state_lock, flags);
++			ret = TMF_RESP_FUNC_COMPLETE;
++		} else {
++			spin_lock_irqsave(&task->task_state_lock, flags);
++			task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
++						    SAS_TASK_STATE_PENDING);
++			spin_unlock_irqrestore(&task->task_state_lock, flags);
++		}
+ 
+-		/* Stopping and SMP devices are not sent a TMF, and are not
+-		 * reset, but the outstanding I/O request is terminated below.
++		/* STP and SMP devices are not sent a TMF, but the
++		 * outstanding I/O request is terminated below.  This is
++		 * because SATA/STP and SMP discovery path timeouts directly
++		 * call the abort task interface for cleanup.
+ 		 */
++		perform_termination = 1;
++
+ 	} else {
+ 		/* Fill in the tmf stucture */
+ 		isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
+@@ -1203,22 +1160,24 @@ int isci_task_abort_task(struct sas_task *task)
+ 
+ 		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ 
+-		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */
++		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
+ 		ret = isci_task_execute_tmf(isci_host, isci_device, &tmf,
+ 					    ISCI_ABORT_TASK_TIMEOUT_MS);
+ 
+-		if (ret != TMF_RESP_FUNC_COMPLETE)
++		if (ret == TMF_RESP_FUNC_COMPLETE)
++			perform_termination = 1;
++		else
+ 			dev_dbg(&isci_host->pdev->dev,
+-				"%s: isci_task_send_tmf failed\n",
+-				__func__);
++				"%s: isci_task_send_tmf failed\n", __func__);
+ 	}
+-	if (ret == TMF_RESP_FUNC_COMPLETE) {
++	if (perform_termination) {
+ 		set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags);
+ 
+ 		/* 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);
++		isci_terminate_request_core(isci_host, isci_device,
++					    old_request);
+ 	}
+ 
+ 	/* Make sure we do not leave a reference to aborted_io_completion */
+diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
+index c9ccd0b..bc78c0a 100644
+--- a/drivers/scsi/isci/task.h
++++ b/drivers/scsi/isci/task.h
+@@ -226,35 +226,6 @@ enum isci_completion_selection {
+ 	isci_perform_error_io_completion        /* Use sas_task_abort */
+ };
+ 
+-static inline void isci_set_task_doneflags(
+-	struct sas_task *task)
+-{
+-	/* Since no futher action will be taken on this task,
+-	 * make sure to mark it complete from the lldd perspective.
+-	 */
+-	task->task_state_flags |= SAS_TASK_STATE_DONE;
+-	task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+-	task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+-}
+-/**
+- * isci_task_all_done() - This function clears the task bits to indicate the
+- *    LLDD is done with the task.
+- *
+- *
+- */
+-static inline void isci_task_all_done(
+-	struct sas_task *task)
+-{
+-	unsigned long flags;
+-
+-	/* Since no futher action will be taken on this task,
+-	 * make sure to mark it complete from the lldd perspective.
+-	 */
+-	spin_lock_irqsave(&task->task_state_lock, flags);
+-	isci_set_task_doneflags(task);
+-	spin_unlock_irqrestore(&task->task_state_lock, flags);
+-}
+-
+ /**
+  * isci_task_set_completion_status() - This function sets the completion status
+  *    for the request.
+@@ -336,7 +307,9 @@ isci_task_set_completion_status(
+ 		/* Fall through to the normal case... */
+ 	case isci_perform_normal_io_completion:
+ 		/* Normal notification (task_done) */
+-		isci_set_task_doneflags(task);
++		task->task_state_flags |= SAS_TASK_STATE_DONE;
++		task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
++					    SAS_TASK_STATE_PENDING);
+ 		break;
+ 	default:
+ 		WARN_ONCE(1, "unknown task_notification_selection: %d\n",

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0018-SCSI-isci-Remove-redundant-isci_request.ttype-field.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0018-SCSI-isci-Remove-redundant-isci_request.ttype-field.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,251 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:22 -0700
+Subject: [18/25] [SCSI] isci: Remove redundant isci_request.ttype field.
+
+commit 3b34c169f8197e02529fa3ec703703c2ce418c57 upstream.
+
+Use the existing IREQ_TMF flag as a request type indicator.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/remote_device.c |   11 ++++-----
+ drivers/scsi/isci/request.c       |   45 ++++++++++---------------------------
+ drivers/scsi/isci/request.h       |    6 -----
+ drivers/scsi/isci/task.c          |   29 ++++++++++++------------
+ 4 files changed, 31 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
+index 20c77ed..9d9e33d 100644
+--- a/drivers/scsi/isci/remote_device.c
++++ b/drivers/scsi/isci/remote_device.c
+@@ -1463,15 +1463,12 @@ void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote
+ 		dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n",
+ 			 __func__, idev, isci_request);
+ 
+-		if (isci_request->ttype == io_task) {
++		if (!test_bit(IREQ_TMF, &isci_request->flags)) {
++			struct sas_task *task = isci_request_access_task(isci_request);
+ 
+-			unsigned long flags2;
+-			struct sas_task *task = isci_request_access_task(
+-				isci_request);
+-
+-			spin_lock_irqsave(&task->task_state_lock, flags2);
++			spin_lock(&task->task_state_lock);
+ 			task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+-			spin_unlock_irqrestore(&task->task_state_lock, flags2);
++			spin_unlock(&task->task_state_lock);
+ 		}
+ 	}
+ 	spin_unlock_irqrestore(&ihost->scic_lock, flags);
+diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
+index bfc7379..192cb48 100644
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -191,7 +191,7 @@ static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq)
+ 
+ 	task_iu->task_func = isci_tmf->tmf_code;
+ 	task_iu->task_tag =
+-		(ireq->ttype == tmf_task) ?
++		(test_bit(IREQ_TMF, &ireq->flags)) ?
+ 		isci_tmf->io_tag :
+ 		SCI_CONTROLLER_INVALID_IO_TAG;
+ }
+@@ -516,7 +516,7 @@ sci_io_request_construct_sata(struct isci_request *ireq,
+ 	struct domain_device *dev = ireq->target_device->domain_dev;
+ 
+ 	/* check for management protocols */
+-	if (ireq->ttype == tmf_task) {
++	if (test_bit(IREQ_TMF, &ireq->flags)) {
+ 		struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+ 
+ 		if (tmf->tmf_code == isci_tmf_sata_srst_high ||
+@@ -632,7 +632,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
+ 	enum sci_status status = SCI_SUCCESS;
+ 
+ 	/* check for management protocols */
+-	if (ireq->ttype == tmf_task) {
++	if (test_bit(IREQ_TMF, &ireq->flags)) {
+ 		struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+ 
+ 		if (tmf->tmf_code == isci_tmf_sata_srst_high ||
+@@ -2630,14 +2630,8 @@ static void isci_task_save_for_upper_layer_completion(
+ 	switch (task_notification_selection) {
+ 
+ 	case isci_perform_normal_io_completion:
+-
+ 		/* Normal notification (task_done) */
+-		dev_dbg(&host->pdev->dev,
+-			"%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n",
+-			__func__,
+-			task,
+-			task->task_status.resp, response,
+-			task->task_status.stat, status);
++
+ 		/* Add to the completed list. */
+ 		list_add(&request->completed_node,
+ 			 &host->requests_to_complete);
+@@ -2650,13 +2644,6 @@ static void isci_task_save_for_upper_layer_completion(
+ 		/* No notification to libsas because this request is
+ 		 * already in the abort path.
+ 		 */
+-		dev_dbg(&host->pdev->dev,
+-			 "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n",
+-			 __func__,
+-			 task,
+-			 task->task_status.resp, response,
+-			 task->task_status.stat, status);
+-
+ 		/* Wake up whatever process was waiting for this
+ 		 * request to complete.
+ 		 */
+@@ -2673,30 +2660,22 @@ static void isci_task_save_for_upper_layer_completion(
+ 
+ 	case isci_perform_error_io_completion:
+ 		/* Use sas_task_abort */
+-		dev_dbg(&host->pdev->dev,
+-			 "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n",
+-			 __func__,
+-			 task,
+-			 task->task_status.resp, response,
+-			 task->task_status.stat, status);
+ 		/* Add to the aborted list. */
+ 		list_add(&request->completed_node,
+ 			 &host->requests_to_errorback);
+ 		break;
+ 
+ 	default:
+-		dev_dbg(&host->pdev->dev,
+-			 "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n",
+-			 __func__,
+-			 task,
+-			 task->task_status.resp, response,
+-			 task->task_status.stat, status);
+-
+ 		/* Add to the error to libsas list. */
+ 		list_add(&request->completed_node,
+ 			 &host->requests_to_errorback);
+ 		break;
+ 	}
++	dev_dbg(&host->pdev->dev,
++		"%s: %d - task = %p, response=%d (%d), status=%d (%d)\n",
++		__func__, task_notification_selection, task,
++		(task) ? task->task_status.resp : 0, response,
++		(task) ? task->task_status.stat : 0, status);
+ }
+ 
+ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_fis *fis)
+@@ -3079,7 +3058,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
+ 	/* XXX as hch said always creating an internal sas_task for tmf
+ 	 * requests would simplify the driver
+ 	 */
+-	task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL;
++	task = (test_bit(IREQ_TMF, &ireq->flags)) ? NULL : isci_request_access_task(ireq);
+ 
+ 	/* all unaccelerated request types (non ssp or ncq) handled with
+ 	 * substates
+@@ -3563,7 +3542,7 @@ static struct isci_request *isci_io_request_from_tag(struct isci_host *ihost,
+ 
+ 	ireq = isci_request_from_tag(ihost, tag);
+ 	ireq->ttype_ptr.io_task_ptr = task;
+-	ireq->ttype = io_task;
++	clear_bit(IREQ_TMF, &ireq->flags);
+ 	task->lldd_task = ireq;
+ 
+ 	return ireq;
+@@ -3577,7 +3556,7 @@ struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost,
+ 
+ 	ireq = isci_request_from_tag(ihost, tag);
+ 	ireq->ttype_ptr.tmf_task_ptr = isci_tmf;
+-	ireq->ttype = tmf_task;
++	set_bit(IREQ_TMF, &ireq->flags);
+ 
+ 	return ireq;
+ }
+diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
+index f720b97..be38933 100644
+--- a/drivers/scsi/isci/request.h
++++ b/drivers/scsi/isci/request.h
+@@ -77,11 +77,6 @@ enum isci_request_status {
+ 	dead        = 0x07
+ };
+ 
+-enum task_type {
+-	io_task  = 0,
+-	tmf_task = 1
+-};
+-
+ enum sci_request_protocol {
+ 	SCIC_NO_PROTOCOL,
+ 	SCIC_SMP_PROTOCOL,
+@@ -116,7 +111,6 @@ struct isci_request {
+ 	#define IREQ_ACTIVE 3
+ 	unsigned long flags;
+ 	/* XXX kill ttype and ttype_ptr, allocate full sas_task */
+-	enum task_type ttype;
+ 	union ttype_ptr_union {
+ 		struct sas_task *io_task_ptr;   /* When ttype==io_task  */
+ 		struct isci_tmf *tmf_task_ptr;  /* When ttype==tmf_task */
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index ec85beb..80e1a69 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -254,7 +254,7 @@ static enum sci_status isci_sata_management_task_request_build(struct isci_reque
+ 	struct isci_tmf *isci_tmf;
+ 	enum sci_status status;
+ 
+-	if (tmf_task != ireq->ttype)
++	if (!test_bit(IREQ_TMF, &ireq->flags))
+ 		return SCI_FAILURE;
+ 
+ 	isci_tmf = isci_request_access_tmf(ireq);
+@@ -352,18 +352,7 @@ static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_reques
+ 	req_completion = ireq->io_request_completion;
+ 	ireq->io_request_completion = NULL;
+ 
+-	if (ireq->ttype == io_task) {
+-
+-		/* Break links with the sas_task - the callback is done
+-		 * elsewhere.
+-		 */
+-		struct sas_task *task = isci_request_access_task(ireq);
+-
+-		if (task)
+-			task->lldd_task = NULL;
+-
+-		ireq->ttype_ptr.io_task_ptr = NULL;
+-	} else {
++	if (test_bit(IREQ_TMF, &ireq->flags)) {
+ 		/* Break links with the TMF request. */
+ 		struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+ 
+@@ -380,6 +369,16 @@ static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_reques
+ 		ireq->ttype_ptr.tmf_task_ptr = NULL;
+ 		dev_dbg(&ihost->pdev->dev, "%s: tmf_code %d, managed tag %#x\n",
+ 			__func__, tmf->tmf_code, tmf->io_tag);
++	} else {
++		/* Break links with the sas_task - the callback is done
++		 * elsewhere.
++		 */
++		struct sas_task *task = isci_request_access_task(ireq);
++
++		if (task)
++			task->lldd_task = NULL;
++
++		ireq->ttype_ptr.io_task_ptr = NULL;
+ 	}
+ 
+ 	dev_warn(&ihost->pdev->dev, "task context unrecoverable (tag: %#x)\n",
+@@ -803,7 +802,9 @@ void isci_terminate_pending_requests(struct isci_host *ihost,
+ 		dev_dbg(&ihost->pdev->dev,
+ 			 "%s: idev=%p request=%p; task=%p old_state=%d\n",
+ 			 __func__, idev, ireq,
+-			ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL,
++			(!test_bit(IREQ_TMF, &ireq->flags)
++				? isci_request_access_task(ireq)
++				: NULL),
+ 			old_state);
+ 
+ 		/* If the old_state is started:

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0019-SCSI-isci-No-need-to-manage-the-pending-reset-bit-on.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0019-SCSI-isci-No-need-to-manage-the-pending-reset-bit-on.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,90 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:27 -0700
+Subject: [19/25] [SCSI] isci: No need to manage the pending reset bit on
+ pending requests.
+
+commit 5412e25c55fc0b08041a451d8bee6f2b291099c2 upstream.
+
+The lldd does not need to look at or manage the pending device
+reset bit in pending sas_tasks.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/remote_device.c |   35 -----------------------------------
+ drivers/scsi/isci/remote_device.h |    3 +--
+ drivers/scsi/isci/task.c          |    3 ---
+ 3 files changed, 1 insertion(+), 40 deletions(-)
+
+diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
+index 9d9e33d..b207cd3 100644
+--- a/drivers/scsi/isci/remote_device.c
++++ b/drivers/scsi/isci/remote_device.c
+@@ -1438,38 +1438,3 @@ int isci_remote_device_found(struct domain_device *domain_dev)
+ 
+ 	return status == SCI_SUCCESS ? 0 : -ENODEV;
+ }
+-
+-/**
+- * isci_device_clear_reset_pending() - This function will clear if any pending
+- *    reset condition flags on the device.
+- * @request: This parameter is the isci_device object.
+- *
+- * true if there is a reset pending for the device.
+- */
+-void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev)
+-{
+-	struct isci_request *isci_request;
+-	struct isci_request *tmp_req;
+-	unsigned long flags = 0;
+-
+-	dev_dbg(&ihost->pdev->dev, "%s: idev=%p, ihost=%p\n",
+-		 __func__, idev, ihost);
+-
+-	spin_lock_irqsave(&ihost->scic_lock, flags);
+-
+-	/* Clear reset pending on all pending requests. */
+-	list_for_each_entry_safe(isci_request, tmp_req,
+-				 &idev->reqs_in_process, dev_node) {
+-		dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n",
+-			 __func__, idev, isci_request);
+-
+-		if (!test_bit(IREQ_TMF, &isci_request->flags)) {
+-			struct sas_task *task = isci_request_access_task(isci_request);
+-
+-			spin_lock(&task->task_state_lock);
+-			task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+-			spin_unlock(&task->task_state_lock);
+-		}
+-	}
+-	spin_unlock_irqrestore(&ihost->scic_lock, flags);
+-}
+diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
+index bee6dd2..483ee50 100644
+--- a/drivers/scsi/isci/remote_device.h
++++ b/drivers/scsi/isci/remote_device.h
+@@ -132,8 +132,7 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost,
+ 				      struct isci_remote_device *idev);
+ void isci_remote_device_gone(struct domain_device *domain_dev);
+ int isci_remote_device_found(struct domain_device *domain_dev);
+-void isci_device_clear_reset_pending(struct isci_host *ihost,
+-				     struct isci_remote_device *idev);
++
+ /**
+  * sci_remote_device_stop() - This method will stop both transmission and
+  *    reception of link activity for the supplied remote device.  This method
+diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
+index 80e1a69..6d8ff15 100644
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -1570,9 +1570,6 @@ static int isci_reset_device(struct isci_host *ihost,
+ 	}
+ 	spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ 
+-	/* Make sure all pending requests are able to be fully terminated. */
+-	isci_device_clear_reset_pending(ihost, idev);
+-
+ 	/* If this is a device on an expander, disable BCN processing. */
+ 	if (!scsi_is_sas_phy_local(phy))
+ 		set_bit(IPORT_BCN_BLOCKED, &iport->flags);

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0020-SCSI-isci-Fix-hard-reset-timeout-conditions.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0020-SCSI-isci-Fix-hard-reset-timeout-conditions.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,197 @@
+From: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Date: Thu, 27 Oct 2011 15:05:32 -0700
+Subject: [20/25] [SCSI] isci: Fix hard reset timeout conditions.
+
+commit 8e35a1398c5db981cd1a2d7635de9c15dd648527 upstream.
+
+A hard reset can timeout before or after the last phy in the
+port goes away.  If after, then notify the OS that the last
+phy has failed.
+
+The recovery for the failed hard reset has been removed.
+This recovery code was unecessary in that the link would
+recover from the failure normally by a new link reset sequence
+or hotplug of the remote device.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/port.c |  101 +++++++++++++++++++++++++++-------------------
+ drivers/scsi/isci/port.h |    1 +
+ 2 files changed, 60 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
+index 8e59c88..bfeb879 100644
+--- a/drivers/scsi/isci/port.c
++++ b/drivers/scsi/isci/port.c
+@@ -350,6 +350,34 @@ static void isci_port_stop_complete(struct isci_host *ihost,
+ 	dev_dbg(&ihost->pdev->dev, "Port stop complete\n");
+ }
+ 
++
++static bool is_port_ready_state(enum sci_port_states state)
++{
++	switch (state) {
++	case SCI_PORT_READY:
++	case SCI_PORT_SUB_WAITING:
++	case SCI_PORT_SUB_OPERATIONAL:
++	case SCI_PORT_SUB_CONFIGURING:
++		return true;
++	default:
++		return false;
++	}
++}
++
++/* flag dummy rnc hanling when exiting a ready state */
++static void port_state_machine_change(struct isci_port *iport,
++				      enum sci_port_states state)
++{
++	struct sci_base_state_machine *sm = &iport->sm;
++	enum sci_port_states old_state = sm->current_state_id;
++
++	if (is_port_ready_state(old_state) && !is_port_ready_state(state))
++		iport->ready_exit = true;
++
++	sci_change_state(sm, state);
++	iport->ready_exit = false;
++}
++
+ /**
+  * isci_port_hard_reset_complete() - This function is called by the sci core
+  *    when the hard reset complete notification has been received.
+@@ -368,6 +396,26 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port,
+ 	/* Save the status of the hard reset from the port. */
+ 	isci_port->hard_reset_status = completion_status;
+ 
++	if (completion_status != SCI_SUCCESS) {
++
++		/* The reset failed.  The port state is now SCI_PORT_FAILED. */
++		if (isci_port->active_phy_mask == 0) {
++
++			/* Generate the link down now to the host, since it
++			 * was intercepted by the hard reset state machine when
++			 * it really happened.
++			 */
++			isci_port_link_down(isci_port->isci_host,
++					    &isci_port->isci_host->phys[
++						   isci_port->last_active_phy],
++					    isci_port);
++		}
++		/* Advance the port state so that link state changes will be
++		* noticed.
++		*/
++		port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
++
++	}
+ 	complete_all(&isci_port->hard_reset_complete);
+ }
+ 
+@@ -657,6 +705,8 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
+ 	struct isci_host *ihost = iport->owning_controller;
+ 
+ 	iport->active_phy_mask &= ~(1 << iphy->phy_index);
++	if (!iport->active_phy_mask)
++		iport->last_active_phy = iphy->phy_index;
+ 
+ 	iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
+ 
+@@ -683,33 +733,6 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
+ 	}
+ }
+ 
+-static bool is_port_ready_state(enum sci_port_states state)
+-{
+-	switch (state) {
+-	case SCI_PORT_READY:
+-	case SCI_PORT_SUB_WAITING:
+-	case SCI_PORT_SUB_OPERATIONAL:
+-	case SCI_PORT_SUB_CONFIGURING:
+-		return true;
+-	default:
+-		return false;
+-	}
+-}
+-
+-/* flag dummy rnc hanling when exiting a ready state */
+-static void port_state_machine_change(struct isci_port *iport,
+-				      enum sci_port_states state)
+-{
+-	struct sci_base_state_machine *sm = &iport->sm;
+-	enum sci_port_states old_state = sm->current_state_id;
+-
+-	if (is_port_ready_state(old_state) && !is_port_ready_state(state))
+-		iport->ready_exit = true;
+-
+-	sci_change_state(sm, state);
+-	iport->ready_exit = false;
+-}
+-
+ /**
+  * sci_port_general_link_up_handler - phy can be assigned to port?
+  * @sci_port: sci_port object for which has a phy that has gone link up.
+@@ -1622,7 +1645,8 @@ void sci_port_construct(struct isci_port *iport, u8 index,
+ 	iport->logical_port_index  = SCIC_SDS_DUMMY_PORT;
+ 	iport->physical_port_index = index;
+ 	iport->active_phy_mask     = 0;
+-	iport->ready_exit	      = false;
++	iport->last_active_phy     = 0;
++	iport->ready_exit	   = false;
+ 
+ 	iport->owning_controller = ihost;
+ 
+@@ -1676,7 +1700,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
+ {
+ 	unsigned long flags;
+ 	enum sci_status status;
+-	int idx, ret = TMF_RESP_FUNC_COMPLETE;
++	int ret = TMF_RESP_FUNC_COMPLETE;
+ 
+ 	dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
+ 		__func__, iport);
+@@ -1697,8 +1721,13 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
+ 			"%s: iport = %p; hard reset completion\n",
+ 			__func__, iport);
+ 
+-		if (iport->hard_reset_status != SCI_SUCCESS)
++		if (iport->hard_reset_status != SCI_SUCCESS) {
+ 			ret = TMF_RESP_FUNC_FAILED;
++
++			dev_err(&ihost->pdev->dev,
++				"%s: iport = %p; hard reset failed (0x%x)\n",
++				__func__, iport, iport->hard_reset_status);
++		}
+ 	} else {
+ 		ret = TMF_RESP_FUNC_FAILED;
+ 
+@@ -1718,18 +1747,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
+ 			"%s: iport = %p; hard reset failed "
+ 			"(0x%x) - driving explicit link fail for all phys\n",
+ 			__func__, iport, iport->hard_reset_status);
+-
+-		/* Down all phys in the port. */
+-		spin_lock_irqsave(&ihost->scic_lock, flags);
+-		for (idx = 0; idx < SCI_MAX_PHYS; ++idx) {
+-			struct isci_phy *iphy = iport->phy_table[idx];
+-
+-			if (!iphy)
+-				continue;
+-			sci_phy_stop(iphy);
+-			sci_phy_start(iphy);
+-		}
+-		spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ 	}
+ 	return ret;
+ }
+diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
+index b50ecd4..e84d22a 100644
+--- a/drivers/scsi/isci/port.h
++++ b/drivers/scsi/isci/port.h
+@@ -109,6 +109,7 @@ struct isci_port {
+ 	u8 logical_port_index;
+ 	u8 physical_port_index;
+ 	u8 active_phy_mask;
++	u8 last_active_phy;
+ 	u16 reserved_rni;
+ 	u16 reserved_tag;
+ 	u32 started_request_count;

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0021-SCSI-isci-revert-bcn-filtering.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0021-SCSI-isci-revert-bcn-filtering.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,414 @@
+From: Dan Williams <dan.j.williams at intel.com>
+Date: Thu, 27 Oct 2011 15:05:37 -0700
+Subject: [21/25] [SCSI] isci: revert bcn filtering
+
+commit 52d74634335dfc0984ed955ed3c6ad6488495f96 upstream.
+
+The initial bcn filtering implementation was validated on a kernel
+baseline that predated the switch to new libata error handling.  Also,
+prior to that conversion we borrowed the mvsas MVS_DEV_EH approach to
+prevent the unwanted extra ap->ops->phy_reset(ap) that occurred in the
+ata_bus_probe() path.
+
+After the conversion to new libata eh resets at discovery are more
+frequent and get filtered prematurely by IDEV_EH.  The result is that
+our bcn filtering has been blocked from running and at discovery and it
+appears to stall discovery completion to the point of triggering hung
+task timeouts.  So, revert the implementation for now.  When it returns
+it will go into libsas proper.
+
+The domain rediscovery that takes place due to ->lldd_I_T_nexus_reset()
+events should now be properly waited for by the ata_port_wait_eh() call
+in ata_port_probe().  So the hard coded delay in the isci
+->lldd_I_T_nexus_reset() and other libsas drivers should help debounce
+the libsas thread from seeing temporary device removals.
+
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+[bwh: Combine with the earlier changes to this driver in commit 4fcf812ca392
+ ('[SCSI] libsas: export sas_alloc_task()'), which is otherwise unwanted]
+---
+ drivers/scsi/isci/port.c |   45 +--------
+ drivers/scsi/isci/port.h |    5 -
+ drivers/scsi/isci/task.c |  235 ----------------------------------------------
+ 3 files changed, 4 insertions(+), 281 deletions(-)
+
+--- a/drivers/scsi/isci/port.c
++++ b/drivers/scsi/isci/port.c
+@@ -145,48 +145,15 @@ static void sci_port_bcn_enable(struct i
+ 	}
+ }
+ 
+-/* called under sci_lock to stabilize phy:port associations */
+-void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport)
+-{
+-	int i;
+-
+-	clear_bit(IPORT_BCN_BLOCKED, &iport->flags);
+-	wake_up(&ihost->eventq);
+-
+-	if (!test_and_clear_bit(IPORT_BCN_PENDING, &iport->flags))
+-		return;
+-
+-	for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) {
+-		struct isci_phy *iphy = iport->phy_table[i];
+-
+-		if (!iphy)
+-			continue;
+-
+-		ihost->sas_ha.notify_port_event(&iphy->sas_phy,
+-						PORTE_BROADCAST_RCVD);
+-		break;
+-	}
+-}
+-
+ static void isci_port_bc_change_received(struct isci_host *ihost,
+ 					 struct isci_port *iport,
+ 					 struct isci_phy *iphy)
+ {
+-	if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) {
+-		dev_dbg(&ihost->pdev->dev,
+-			"%s: disabled BCN; isci_phy = %p, sas_phy = %p\n",
+-			__func__, iphy, &iphy->sas_phy);
+-		set_bit(IPORT_BCN_PENDING, &iport->flags);
+-		atomic_inc(&iport->event);
+-		wake_up(&ihost->eventq);
+-	} else {
+-		dev_dbg(&ihost->pdev->dev,
+-			"%s: isci_phy = %p, sas_phy = %p\n",
+-			__func__, iphy, &iphy->sas_phy);
++	dev_dbg(&ihost->pdev->dev,
++		"%s: isci_phy = %p, sas_phy = %p\n",
++		__func__, iphy, &iphy->sas_phy);
+ 
+-		ihost->sas_ha.notify_port_event(&iphy->sas_phy,
+-						PORTE_BROADCAST_RCVD);
+-	}
++	ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
+ 	sci_port_bcn_enable(iport);
+ }
+ 
+@@ -278,9 +245,6 @@ static void isci_port_link_down(struct i
+ 		/* check to see if this is the last phy on this port. */
+ 		if (isci_phy->sas_phy.port &&
+ 		    isci_phy->sas_phy.port->num_phys == 1) {
+-			atomic_inc(&isci_port->event);
+-			isci_port_bcn_enable(isci_host, isci_port);
+-
+ 			/* change the state for all devices on this port.  The
+ 			 * next task sent to this device will be returned as
+ 			 * SAS_TASK_UNDELIVERED, and the scsi mid layer will
+@@ -1672,7 +1636,6 @@ void isci_port_init(struct isci_port *ip
+ 	init_completion(&iport->start_complete);
+ 	iport->isci_host = ihost;
+ 	isci_port_change_state(iport, isci_freed);
+-	atomic_set(&iport->event, 0);
+ }
+ 
+ /**
+--- a/drivers/scsi/isci/port.h
++++ b/drivers/scsi/isci/port.h
+@@ -77,7 +77,6 @@ enum isci_status {
+ 
+ /**
+  * struct isci_port - isci direct attached sas port object
+- * @event: counts bcns and port stop events (for bcn filtering)
+  * @ready_exit: several states constitute 'ready'. When exiting ready we
+  *              need to take extra port-teardown actions that are
+  *              skipped when exiting to another 'ready' state.
+@@ -92,10 +91,6 @@ enum isci_status {
+  */
+ struct isci_port {
+ 	enum isci_status status;
+-	#define IPORT_BCN_BLOCKED 0
+-	#define IPORT_BCN_PENDING 1
+-	unsigned long flags;
+-	atomic_t event;
+ 	struct isci_host *isci_host;
+ 	struct asd_sas_port sas_port;
+ 	struct list_head remote_dev_list;
+--- a/drivers/scsi/isci/task.c
++++ b/drivers/scsi/isci/task.c
+@@ -1331,249 +1331,10 @@ isci_task_request_complete(struct isci_h
+ 		complete(tmf_complete);
+ }
+ 
+-static void isci_smp_task_timedout(unsigned long _task)
+-{
+-	struct sas_task *task = (void *) _task;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&task->task_state_lock, flags);
+-	if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
+-		task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+-	spin_unlock_irqrestore(&task->task_state_lock, flags);
+-
+-	complete(&task->completion);
+-}
+-
+-static void isci_smp_task_done(struct sas_task *task)
+-{
+-	if (!del_timer(&task->timer))
+-		return;
+-	complete(&task->completion);
+-}
+-
+-static struct sas_task *isci_alloc_task(void)
+-{
+-	struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL);
+-
+-	if (task) {
+-		INIT_LIST_HEAD(&task->list);
+-		spin_lock_init(&task->task_state_lock);
+-		task->task_state_flags = SAS_TASK_STATE_PENDING;
+-		init_timer(&task->timer);
+-		init_completion(&task->completion);
+-	}
+-
+-	return task;
+-}
+-
+-static void isci_free_task(struct isci_host *ihost, struct sas_task  *task)
+-{
+-	if (task) {
+-		BUG_ON(!list_empty(&task->list));
+-		kfree(task);
+-	}
+-}
+-
+-static int isci_smp_execute_task(struct isci_host *ihost,
+-				 struct domain_device *dev, void *req,
+-				 int req_size, void *resp, int resp_size)
+-{
+-	int res, retry;
+-	struct sas_task *task = NULL;
+-
+-	for (retry = 0; retry < 3; retry++) {
+-		task = isci_alloc_task();
+-		if (!task)
+-			return -ENOMEM;
+-
+-		task->dev = dev;
+-		task->task_proto = dev->tproto;
+-		sg_init_one(&task->smp_task.smp_req, req, req_size);
+-		sg_init_one(&task->smp_task.smp_resp, resp, resp_size);
+-
+-		task->task_done = isci_smp_task_done;
+-
+-		task->timer.data = (unsigned long) task;
+-		task->timer.function = isci_smp_task_timedout;
+-		task->timer.expires = jiffies + 10*HZ;
+-		add_timer(&task->timer);
+-
+-		res = isci_task_execute_task(task, 1, GFP_KERNEL);
+-
+-		if (res) {
+-			del_timer(&task->timer);
+-			dev_dbg(&ihost->pdev->dev,
+-				"%s: executing SMP task failed:%d\n",
+-				__func__, res);
+-			goto ex_err;
+-		}
+-
+-		wait_for_completion(&task->completion);
+-		res = -ECOMM;
+-		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+-			dev_dbg(&ihost->pdev->dev,
+-				"%s: smp task timed out or aborted\n",
+-				__func__);
+-			isci_task_abort_task(task);
+-			if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+-				dev_dbg(&ihost->pdev->dev,
+-					"%s: SMP task aborted and not done\n",
+-					__func__);
+-				goto ex_err;
+-			}
+-		}
+-		if (task->task_status.resp == SAS_TASK_COMPLETE &&
+-		    task->task_status.stat == SAM_STAT_GOOD) {
+-			res = 0;
+-			break;
+-		}
+-		if (task->task_status.resp == SAS_TASK_COMPLETE &&
+-		      task->task_status.stat == SAS_DATA_UNDERRUN) {
+-			/* no error, but return the number of bytes of
+-			* underrun */
+-			res = task->task_status.residual;
+-			break;
+-		}
+-		if (task->task_status.resp == SAS_TASK_COMPLETE &&
+-		      task->task_status.stat == SAS_DATA_OVERRUN) {
+-			res = -EMSGSIZE;
+-			break;
+-		} else {
+-			dev_dbg(&ihost->pdev->dev,
+-				"%s: task to dev %016llx response: 0x%x "
+-				"status 0x%x\n", __func__,
+-				SAS_ADDR(dev->sas_addr),
+-				task->task_status.resp,
+-				task->task_status.stat);
+-			isci_free_task(ihost, task);
+-			task = NULL;
+-		}
+-	}
+-ex_err:
+-	BUG_ON(retry == 3 && task != NULL);
+-	isci_free_task(ihost, task);
+-	return res;
+-}
+-
+-#define DISCOVER_REQ_SIZE  16
+-#define DISCOVER_RESP_SIZE 56
+-
+-int isci_smp_get_phy_attached_dev_type(struct isci_host *ihost,
+-				       struct domain_device *dev,
+-				       int phy_id, int *adt)
+-{
+-	struct smp_resp *disc_resp;
+-	u8 *disc_req;
+-	int res;
+-
+-	disc_resp = kzalloc(DISCOVER_RESP_SIZE, GFP_KERNEL);
+-	if (!disc_resp)
+-		return -ENOMEM;
+-
+-	disc_req = kzalloc(DISCOVER_REQ_SIZE, GFP_KERNEL);
+-	if (disc_req) {
+-		disc_req[0] = SMP_REQUEST;
+-		disc_req[1] = SMP_DISCOVER;
+-		disc_req[9] = phy_id;
+-	} else {
+-		kfree(disc_resp);
+-		return -ENOMEM;
+-	}
+-	res = isci_smp_execute_task(ihost, dev, disc_req, DISCOVER_REQ_SIZE,
+-				    disc_resp, DISCOVER_RESP_SIZE);
+-	if (!res) {
+-		if (disc_resp->result != SMP_RESP_FUNC_ACC)
+-			res = disc_resp->result;
+-		else
+-			*adt = disc_resp->disc.attached_dev_type;
+-	}
+-	kfree(disc_req);
+-	kfree(disc_resp);
+-
+-	return res;
+-}
+-
+-static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy_num)
+-{
+-	struct domain_device *dev = idev->domain_dev;
+-	struct isci_port *iport = idev->isci_port;
+-	struct isci_host *ihost = iport->isci_host;
+-	int res, iteration = 0, attached_device_type;
+-	#define STP_WAIT_MSECS 25000
+-	unsigned long tmo = msecs_to_jiffies(STP_WAIT_MSECS);
+-	unsigned long deadline = jiffies + tmo;
+-	enum {
+-		SMP_PHYWAIT_PHYDOWN,
+-		SMP_PHYWAIT_PHYUP,
+-		SMP_PHYWAIT_DONE
+-	} phy_state = SMP_PHYWAIT_PHYDOWN;
+-
+-	/* While there is time, wait for the phy to go away and come back */
+-	while (time_is_after_jiffies(deadline) && phy_state != SMP_PHYWAIT_DONE) {
+-		int event = atomic_read(&iport->event);
+-
+-		++iteration;
+-
+-		tmo = wait_event_timeout(ihost->eventq,
+-					 event != atomic_read(&iport->event) ||
+-					 !test_bit(IPORT_BCN_BLOCKED, &iport->flags),
+-					 tmo);
+-		/* link down, stop polling */
+-		if (!test_bit(IPORT_BCN_BLOCKED, &iport->flags))
+-			break;
+-
+-		dev_dbg(&ihost->pdev->dev,
+-			"%s: iport %p, iteration %d,"
+-			" phase %d: time_remaining %lu, bcns = %d\n",
+-			__func__, iport, iteration, phy_state,
+-			tmo, test_bit(IPORT_BCN_PENDING, &iport->flags));
+-
+-		res = isci_smp_get_phy_attached_dev_type(ihost, dev, phy_num,
+-							 &attached_device_type);
+-		tmo = deadline - jiffies;
+-
+-		if (res) {
+-			dev_dbg(&ihost->pdev->dev,
+-				 "%s: iteration %d, phase %d:"
+-				 " SMP error=%d, time_remaining=%lu\n",
+-				 __func__, iteration, phy_state, res, tmo);
+-			break;
+-		}
+-		dev_dbg(&ihost->pdev->dev,
+-			"%s: iport %p, iteration %d,"
+-			" phase %d: time_remaining %lu, bcns = %d, "
+-			"attdevtype = %x\n",
+-			__func__, iport, iteration, phy_state,
+-			tmo, test_bit(IPORT_BCN_PENDING, &iport->flags),
+-			attached_device_type);
+-
+-		switch (phy_state) {
+-		case SMP_PHYWAIT_PHYDOWN:
+-			/* Has the device gone away? */
+-			if (!attached_device_type)
+-				phy_state = SMP_PHYWAIT_PHYUP;
+-
+-			break;
+-
+-		case SMP_PHYWAIT_PHYUP:
+-			/* Has the device come back? */
+-			if (attached_device_type)
+-				phy_state = SMP_PHYWAIT_DONE;
+-			break;
+-
+-		case SMP_PHYWAIT_DONE:
+-			break;
+-		}
+-
+-	}
+-	dev_dbg(&ihost->pdev->dev, "%s: done\n",  __func__);
+-}
+-
+ static int isci_reset_device(struct isci_host *ihost,
+ 			     struct isci_remote_device *idev)
+ {
+ 	struct sas_phy *phy = sas_find_local_phy(idev->domain_dev);
+-	struct isci_port *iport = idev->isci_port;
+ 	enum sci_status status;
+ 	unsigned long flags;
+ 	int rc;
+@@ -1593,10 +1354,6 @@ static int isci_reset_device(struct isci
+ 	}
+ 	spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ 
+-	/* If this is a device on an expander, disable BCN processing. */
+-	if (!scsi_is_sas_phy_local(phy))
+-		set_bit(IPORT_BCN_BLOCKED, &iport->flags);
+-
+ 	rc = sas_phy_reset(phy, true);
+ 
+ 	/* Terminate in-progress I/O now. */
+@@ -1607,21 +1364,6 @@ static int isci_reset_device(struct isci
+ 	status = sci_remote_device_reset_complete(idev);
+ 	spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ 
+-	/* If this is a device on an expander, bring the phy back up. */
+-	if (!scsi_is_sas_phy_local(phy)) {
+-		/* A phy reset will cause the device to go away then reappear.
+-		 * Since libsas will take action on incoming BCNs (eg. remove
+-		 * a device going through an SMP phy-control driven reset),
+-		 * we need to wait until the phy comes back up before letting
+-		 * discovery proceed in libsas.
+-		 */
+-		isci_wait_for_smp_phy_reset(idev, phy->number);
+-
+-		spin_lock_irqsave(&ihost->scic_lock, flags);
+-		isci_port_bcn_enable(ihost, idev->isci_port);
+-		spin_unlock_irqrestore(&ihost->scic_lock, flags);
+-	}
+-
+ 	if (status != SCI_SUCCESS) {
+ 		dev_dbg(&ihost->pdev->dev,
+ 			 "%s: sci_remote_device_reset_complete(%p) "

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0022-SCSI-isci-overriding-max_concurr_spinup-oem-paramete.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0022-SCSI-isci-overriding-max_concurr_spinup-oem-paramete.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,126 @@
+From: Andrzej Jakowski <andrzej.jakowski at intel.com>
+Date: Thu, 27 Oct 2011 15:05:42 -0700
+Subject: [22/25] [SCSI] isci: overriding max_concurr_spinup oem parameter by
+ max(oem, user)
+
+commit 7000f7c71e2457391e3249eac1ae53c91f49a8c0 upstream.
+
+Fixes bug where max_concurr_spinup oem parameter should be
+overriden by max_concurr_spinup user parameter. Override should
+happen only when max_concurr_spinup user parameter is specified
+in command line (greater than 0). Also this fix shortens variables
+representing max_conxurr_spinup for oem and user parameters.
+
+Signed-off-by: Andrzej Jakowski <andrzej.jakowski at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+---
+ drivers/scsi/isci/host.c       |   23 ++++++++++++++++-------
+ drivers/scsi/isci/init.c       |    2 +-
+ drivers/scsi/isci/probe_roms.h |    4 ++--
+ 3 files changed, 19 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
+index f07f30f..e7fe9c4 100644
+--- a/drivers/scsi/isci/host.c
++++ b/drivers/scsi/isci/host.c
+@@ -1350,7 +1350,7 @@ static void isci_user_parameters_get(struct sci_user_parameters *u)
+ 	u->stp_max_occupancy_timeout = stp_max_occ_to;
+ 	u->ssp_max_occupancy_timeout = ssp_max_occ_to;
+ 	u->no_outbound_task_timeout = no_outbound_task_to;
+-	u->max_number_concurrent_device_spin_up = max_concurr_spinup;
++	u->max_concurr_spinup = max_concurr_spinup;
+ }
+ 
+ static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm)
+@@ -1661,7 +1661,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
+ 	ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+ 
+ 	/* Default to APC mode. */
+-	ihost->oem_parameters.controller.max_concurrent_dev_spin_up = 1;
++	ihost->oem_parameters.controller.max_concurr_spin_up = 1;
+ 
+ 	/* Default to no SSC operation. */
+ 	ihost->oem_parameters.controller.do_enable_ssc = false;
+@@ -1787,7 +1787,8 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
+ 	} else
+ 		return -EINVAL;
+ 
+-	if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
++	if (oem->controller.max_concurr_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT ||
++	    oem->controller.max_concurr_spin_up < 1)
+ 		return -EINVAL;
+ 
+ 	return 0;
+@@ -1810,6 +1811,16 @@ static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
+ 	return SCI_FAILURE_INVALID_STATE;
+ }
+ 
++static u8 max_spin_up(struct isci_host *ihost)
++{
++	if (ihost->user_parameters.max_concurr_spinup)
++		return min_t(u8, ihost->user_parameters.max_concurr_spinup,
++			     MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
++	else
++		return min_t(u8, ihost->oem_parameters.controller.max_concurr_spin_up,
++			     MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
++}
++
+ static void power_control_timeout(unsigned long data)
+ {
+ 	struct sci_timer *tmr = (struct sci_timer *)data;
+@@ -1839,8 +1850,7 @@ static void power_control_timeout(unsigned long data)
+ 		if (iphy == NULL)
+ 			continue;
+ 
+-		if (ihost->power_control.phys_granted_power >=
+-		    ihost->oem_parameters.controller.max_concurrent_dev_spin_up)
++		if (ihost->power_control.phys_granted_power >= max_spin_up(ihost))
+ 			break;
+ 
+ 		ihost->power_control.requesters[i] = NULL;
+@@ -1865,8 +1875,7 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
+ {
+ 	BUG_ON(iphy == NULL);
+ 
+-	if (ihost->power_control.phys_granted_power <
+-	    ihost->oem_parameters.controller.max_concurrent_dev_spin_up) {
++	if (ihost->power_control.phys_granted_power < max_spin_up(ihost)) {
+ 		ihost->power_control.phys_granted_power++;
+ 		sci_phy_consume_power_handler(iphy);
+ 
+diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
+index 43fe840..a97edab 100644
+--- a/drivers/scsi/isci/init.c
++++ b/drivers/scsi/isci/init.c
+@@ -118,7 +118,7 @@ unsigned char phy_gen = 3;
+ module_param(phy_gen, byte, 0);
+ MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
+ 
+-unsigned char max_concurr_spinup = 1;
++unsigned char max_concurr_spinup;
+ module_param(max_concurr_spinup, byte, 0);
+ MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
+ 
+diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
+index dc007e6..2c75248 100644
+--- a/drivers/scsi/isci/probe_roms.h
++++ b/drivers/scsi/isci/probe_roms.h
+@@ -112,7 +112,7 @@ struct sci_user_parameters {
+ 	 * This field specifies the maximum number of direct attached devices
+ 	 * that can have power supplied to them simultaneously.
+ 	 */
+-	u8 max_number_concurrent_device_spin_up;
++	u8 max_concurr_spinup;
+ 
+ 	/**
+ 	 * This field specifies the number of seconds to allow a phy to consume
+@@ -219,7 +219,7 @@ struct sci_bios_oem_param_block_hdr {
+ struct sci_oem_params {
+ 	struct {
+ 		uint8_t mode_type;
+-		uint8_t max_concurrent_dev_spin_up;
++		uint8_t max_concurr_spin_up;
+ 		uint8_t do_enable_ssc;
+ 		uint8_t reserved;
+ 	} controller;

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0023-isci-fix-oem-parameter-validation-on-single-controll.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0023-isci-fix-oem-parameter-validation-on-single-controll.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,43 @@
+From: Dan Williams <dan.j.williams at intel.com>
+Date: Mon, 30 Apr 2012 11:57:44 -0700
+Subject: [23/25] isci: fix oem parameter validation on single controller skus
+
+commit cec5997b4e3d58dbe2fa6d54da49065d21cf45e4 upstream.
+
+commit fc25f79af321c01a739150ba2c09435cf977a63d upstream.
+
+OEM parameters [1] are parsed from the platform option-rom / efi
+driver.  By default the driver was validating the parameters for the
+dual-controller case, but in single-controller case only the first set
+of parameters may be valid.
+
+Limit the validation to the number of actual controllers detected
+otherwise the driver may fail to parse the valid parameters leading to
+driver-load or runtime failures.
+
+[1] the platform specific set of phy address, configuration,and analog
+    tuning values
+
+[stable v3.0+]
+Reported-by: Dave Jiang <dave.jiang at intel.com>
+Tested-by: Dave Jiang <dave.jiang at intel.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ drivers/scsi/isci/init.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
+index a97edab..83d08b6 100644
+--- a/drivers/scsi/isci/init.c
++++ b/drivers/scsi/isci/init.c
+@@ -465,7 +465,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
+ 	if (!orom)
+ 		orom = isci_request_oprom(pdev);
+ 
+-	for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
++	for (i = 0; orom && i < num_controllers(pdev); i++) {
+ 		if (sci_oem_parameters_validate(&orom->ctrl[i])) {
+ 			dev_warn(&pdev->dev,
+ 				 "[%d]: invalid oem parameters detected, falling back to firmware\n", i);

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0024-isci-fix-isci_pci_probe-generates-warning-on-efi-fai.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0024-isci-fix-isci_pci_probe-generates-warning-on-efi-fai.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,49 @@
+From: Dan Williams <dan.j.williams at intel.com>
+Date: Fri, 22 Jun 2012 11:31:14 -0700
+Subject: [24/25] isci: fix isci_pci_probe() generates warning on efi failure
+ path
+
+commit d562efad2326a7c2383a211f41d0d4121fad5d4b upstream.
+
+commit 6d70a74ffd616073a68ae0974d98819bfa8e6da6 upstream.
+
+The oem parameter image embedded in the efi variable is at an offset
+from the start of the variable.  However, in the failure path we try to
+free the 'orom' pointer which is only valid when the paramaters are
+being read from the legacy option-rom space.
+
+Since failure to load the oem parameters is unlikely and we keep the
+memory around in the success case just defer all de-allocation to devm.
+
+Reported-by: Don Morris <don.morris at hp.com>
+Signed-off-by: Dan Williams <dan.j.williams at intel.com>
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ drivers/scsi/isci/init.c       |    1 -
+ drivers/scsi/isci/probe_roms.c |    1 -
+ 2 files changed, 2 deletions(-)
+
+diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
+index 83d08b6..5c8b0dc 100644
+--- a/drivers/scsi/isci/init.c
++++ b/drivers/scsi/isci/init.c
+@@ -469,7 +469,6 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
+ 		if (sci_oem_parameters_validate(&orom->ctrl[i])) {
+ 			dev_warn(&pdev->dev,
+ 				 "[%d]: invalid oem parameters detected, falling back to firmware\n", i);
+-			devm_kfree(&pdev->dev, orom);
+ 			orom = NULL;
+ 			break;
+ 		}
+diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
+index b5f4341..7cd637d 100644
+--- a/drivers/scsi/isci/probe_roms.c
++++ b/drivers/scsi/isci/probe_roms.c
+@@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
+ 
+ 	if (i >= len) {
+ 		dev_err(&pdev->dev, "oprom parse error\n");
+-		devm_kfree(&pdev->dev, rom);
+ 		rom = NULL;
+ 	}
+ 	pci_unmap_biosrom(oprom);

Added: dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0025-isci-copy-fis-0x34-response-into-proper-buffer.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/x86/isci/0025-isci-copy-fis-0x34-response-into-proper-buffer.patch	Mon Jan 14 01:10:00 2013	(r19726)
@@ -0,0 +1,36 @@
+From: Maciej Patelczyk <maciej.patelczyk at intel.com>
+Date: Mon, 15 Oct 2012 14:29:03 +0200
+Subject: [25/25] isci: copy fis 0x34 response into proper buffer
+
+commit 733dcd5a3d61164b794d461750aed607cd46120d upstream.
+
+commit 49bd665c5407a453736d3232ee58f2906b42e83c upstream.
+
+SATA MICROCODE DOWNALOAD fails on isci driver. After receiving Register
+Device to Host (FIS 0x34) frame Initiator resets phy.
+In the frame handler routine response (FIS 0x34) was copied into wrong
+buffer and upper layer did not receive any answer which resulted in
+timeout and reset.
+This patch corrects this bug.
+
+Signed-off-by: Maciej Patelczyk <maciej.patelczyk at intel.com>
+Signed-off-by: Lukasz Dorau <lukasz.dorau at intel.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ drivers/scsi/isci/request.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
+index 192cb48..f3cbecc 100644
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -1849,7 +1849,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
+ 								      frame_index,
+ 								      (void **)&frame_buffer);
+ 
+-			sci_controller_copy_sata_response(&ireq->stp.req,
++			sci_controller_copy_sata_response(&ireq->stp.rsp,
+ 							       frame_header,
+ 							       frame_buffer);
+ 

Modified: dists/squeeze/linux-2.6/debian/patches/series/47
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/series/47	Sun Jan 13 00:12:05 2013	(r19725)
+++ dists/squeeze/linux-2.6/debian/patches/series/47	Mon Jan 14 01:10:00 2013	(r19726)
@@ -172,3 +172,24 @@
 + debian/random-Avoid-ABI-change-in-irq_desc.patch
 + debian/epoll-Avoid-ABI-change-in-file.patch
 + bugfix/x86/drm-i915-Attempt-to-fix-watermark-setup-on-85x-v2.patch
++ features/x86/isci/0002-treewide-remove-extra-semicolons-from-various-parts-.patch
++ features/x86/isci/0005-SCSI-isci-fix-support-for-large-smp-requests.patch
++ features/x86/isci/0006-SCSI-isci-fix-missed-unlock-in-apc_agent_timeout.patch
++ features/x86/isci/0007-SCSI-isci-atapi-support.patch
++ features/x86/isci/0008-SCSI-isci-SATA-STP-I-O-is-only-returned-in-the-norma.patch
++ features/x86/isci/0009-SCSI-isci-fix-decode-of-DONE_CRC_ERR-TC-completion-s.patch
++ features/x86/isci/0010-SCSI-isci-The-port-state-should-be-set-to-stopping-o.patch
++ features/x86/isci/0012-SCSI-isci-Lookup-device-references-through-requests-.patch
++ features/x86/isci/0013-SCSI-isci-Immediately-fail-I-O-to-removed-devices.patch
++ features/x86/isci/0014-SCSI-isci-Fix-tag-leak-in-tasks-and-terminated-reque.patch
++ features/x86/isci/0015-SCSI-isci-Handle-task-request-timeouts-correctly.patch
++ features/x86/isci/0016-SCSI-isci-No-task_done-callbacks-in-error-handler-pa.patch
++ features/x86/isci/0017-SCSI-isci-Fix-task-management-for-SMP-SATA-and-on-de.patch
++ features/x86/isci/0018-SCSI-isci-Remove-redundant-isci_request.ttype-field.patch
++ features/x86/isci/0019-SCSI-isci-No-need-to-manage-the-pending-reset-bit-on.patch
++ features/x86/isci/0020-SCSI-isci-Fix-hard-reset-timeout-conditions.patch
++ features/x86/isci/0021-SCSI-isci-revert-bcn-filtering.patch
++ features/x86/isci/0022-SCSI-isci-overriding-max_concurr_spinup-oem-paramete.patch
++ features/x86/isci/0023-isci-fix-oem-parameter-validation-on-single-controll.patch
++ features/x86/isci/0024-isci-fix-isci_pci_probe-generates-warning-on-efi-fai.patch
++ features/x86/isci/0025-isci-copy-fis-0x34-response-into-proper-buffer.patch



More information about the Kernel-svn-changes mailing list