diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-01-31 00:13:33 -0500 |
---|---|---|
committer | Jody McIntyre <scjody@modernduck.com> | 2006-02-23 00:28:52 -0500 |
commit | 35bdddb83f62978b5fad82a14fbfd78cc3a5a60c (patch) | |
tree | b5fcfd00b9af8815dd42e3d65e2f9f2e453f4a89 /drivers/ieee1394/sbp2.c | |
parent | bf637ec3ef4159da3dd156ecf6f6987d8c8c5dae (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.c | 64 |
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 | } |