[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