aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/sbp2.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-01-31 00:13:33 -0500
committerJody McIntyre <scjody@modernduck.com>2006-02-23 00:28:52 -0500
commit35bdddb83f62978b5fad82a14fbfd78cc3a5a60c (patch)
treeb5fcfd00b9af8815dd42e3d65e2f9f2e453f4a89 /drivers/ieee1394/sbp2.c
parentbf637ec3ef4159da3dd156ecf6f6987d8c8c5dae (diff)
sbp2: variable status FIFO address (fix login timeout)
Let the ieee1394 core select a suitable 1394 address range for sbp2's status FIFO instead of using a fixed range. Since the core only selects addresses which are guaranteed to be out of the "physical range" as per OHCI 1.1, this patch also fixes an old bug: OHCI controllers which implement a writeable PhysicalUpperBound register included sbp2's status FIFO in the physical range. That way sbp2 was never notified of a succesful login and always failed after timeout. Affected OHCI host adapters include ALi and Fujitsu controllers. As another side effect of this patch, the status FIFO is no longer located in a range for which OHCI chips perform "posted writes". Each status write now requires a response subaction. But since large data transfers involve only few status writes, there is no measurable decrease of I/O throughput. What's more, the status FIFO is now safe from potential host bus errors. Nevertheless, posted writes could be re-enabled by extensions to the ARM features of the 1394 stack. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Jody McIntyre <scjody@modernduck.com> (cherry picked from b2d38cccad4ef80d6b672b8f89aae5fe2907b113 commit)
Diffstat (limited to 'drivers/ieee1394/sbp2.c')
-rw-r--r--drivers/ieee1394/sbp2.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 8963dd484eb9..0672224fa109 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -748,11 +748,6 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
748 hi->host = ud->ne->host; 748 hi->host = ud->ne->host;
749 INIT_LIST_HEAD(&hi->scsi_ids); 749 INIT_LIST_HEAD(&hi->scsi_ids);
750 750
751 /* Register our sbp2 status address space... */
752 hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops,
753 SBP2_STATUS_FIFO_ADDRESS,
754 SBP2_STATUS_FIFO_ADDRESS +
755 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));
756#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA 751#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
757 /* Handle data movement if physical dma is not 752 /* Handle data movement if physical dma is not
758 * enabled/supportedon host controller */ 753 * enabled/supportedon host controller */
@@ -765,6 +760,18 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
765 760
766 list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); 761 list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
767 762
763 /* Register the status FIFO address range. We could use the same FIFO
764 * for targets at different nodes. However we need different FIFOs per
765 * target in order to support multi-unit devices. */
766 scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
767 &sbp2_highlevel, ud->ne->host, &sbp2_ops,
768 sizeof(struct sbp2_status_block), sizeof(quadlet_t),
769 ~0ULL, ~0ULL);
770 if (!scsi_id->status_fifo_addr) {
771 SBP2_ERR("failed to allocate status FIFO address range");
772 goto failed_alloc;
773 }
774
768 /* Register our host with the SCSI stack. */ 775 /* Register our host with the SCSI stack. */
769 scsi_host = scsi_host_alloc(&scsi_driver_template, 776 scsi_host = scsi_host_alloc(&scsi_driver_template,
770 sizeof(unsigned long)); 777 sizeof(unsigned long));
@@ -1003,6 +1010,10 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
1003 SBP2_DMA_FREE("single query logins data"); 1010 SBP2_DMA_FREE("single query logins data");
1004 } 1011 }
1005 1012
1013 if (scsi_id->status_fifo_addr)
1014 hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
1015 scsi_id->status_fifo_addr);
1016
1006 scsi_id->ud->device.driver_data = NULL; 1017 scsi_id->ud->device.driver_data = NULL;
1007 1018
1008 SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); 1019 SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
@@ -1081,11 +1092,10 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
1081 ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); 1092 ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
1082 SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); 1093 SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
1083 1094
1084 scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 1095 scsi_id->query_logins_orb->status_fifo_hi =
1085 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); 1096 ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
1086 scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | 1097 scsi_id->query_logins_orb->status_fifo_lo =
1087 SBP2_STATUS_FIFO_ADDRESS_HI); 1098 ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
1088 SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
1089 1099
1090 sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); 1100 sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
1091 1101
@@ -1190,11 +1200,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
1190 ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); 1200 ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
1191 SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); 1201 SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
1192 1202
1193 scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 1203 scsi_id->login_orb->status_fifo_hi =
1194 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); 1204 ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
1195 scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | 1205 scsi_id->login_orb->status_fifo_lo =
1196 SBP2_STATUS_FIFO_ADDRESS_HI); 1206 ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
1197 SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
1198 1207
1199 /* 1208 /*
1200 * Byte swap ORB if necessary 1209 * Byte swap ORB if necessary
@@ -1307,10 +1316,10 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
1307 scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); 1316 scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
1308 1317
1309 scsi_id->logout_orb->reserved5 = 0x0; 1318 scsi_id->logout_orb->reserved5 = 0x0;
1310 scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 1319 scsi_id->logout_orb->status_fifo_hi =
1311 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); 1320 ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
1312 scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | 1321 scsi_id->logout_orb->status_fifo_lo =
1313 SBP2_STATUS_FIFO_ADDRESS_HI); 1322 ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
1314 1323
1315 /* 1324 /*
1316 * Byte swap ORB if necessary 1325 * Byte swap ORB if necessary
@@ -1372,10 +1381,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
1372 scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); 1381 scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
1373 1382
1374 scsi_id->reconnect_orb->reserved5 = 0x0; 1383 scsi_id->reconnect_orb->reserved5 = 0x0;
1375 scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 1384 scsi_id->reconnect_orb->status_fifo_hi =
1376 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); 1385 ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
1377 scsi_id->reconnect_orb->status_FIFO_hi = 1386 scsi_id->reconnect_orb->status_fifo_lo =
1378 (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); 1387 ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
1379 1388
1380 /* 1389 /*
1381 * Byte swap ORB if necessary 1390 * Byte swap ORB if necessary
@@ -2112,7 +2121,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
2112{ 2121{
2113 struct sbp2scsi_host_info *hi; 2122 struct sbp2scsi_host_info *hi;
2114 struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; 2123 struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
2115 u32 id;
2116 struct scsi_cmnd *SCpnt = NULL; 2124 struct scsi_cmnd *SCpnt = NULL;
2117 u32 scsi_status = SBP2_SCSI_STATUS_GOOD; 2125 u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
2118 struct sbp2_command_info *command; 2126 struct sbp2_command_info *command;
@@ -2135,12 +2143,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
2135 } 2143 }
2136 2144
2137 /* 2145 /*
2138 * Find our scsi_id structure by looking at the status fifo address written to by 2146 * Find our scsi_id structure by looking at the status fifo address
2139 * the sbp2 device. 2147 * written to by the sbp2 device.
2140 */ 2148 */
2141 id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS));
2142 list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { 2149 list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) {
2143 if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) { 2150 if (scsi_id_tmp->ne->nodeid == nodeid &&
2151 scsi_id_tmp->status_fifo_addr == addr) {
2144 scsi_id = scsi_id_tmp; 2152 scsi_id = scsi_id_tmp;
2145 break; 2153 break;
2146 } 2154 }