diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-07-23 16:18:00 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-09-17 13:29:24 -0400 |
commit | 6065772d54a3b994b9b5d3df6413ec6a1c8c2ec1 (patch) | |
tree | ad4eff582622e00443e1a685d8d8a2553412edc0 /drivers/ieee1394 | |
parent | 3e98eab46d1a482532c653bdb0c006413654d171 (diff) |
ieee1394: sbp2: more checks of status block
- Add checks for the (very unlikely) cases that the target writes too
little or too much status data or writes unsolicited status.
- Indicate that these and similar conditions are unlikely().
- Check the 'resp' and 'sbp_status' fields for possible failure status.
- Slightly optimize access macros for the status block bitfields.
- Unify a few related log messages.
TODO: Check if 'src'==1, then withhold the respective ORB from reuse
until status for any subsequent ORB was received. This is an old bug
whose fix requires more complex command queue handling.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/sbp2.c | 70 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.h | 14 |
2 files changed, 38 insertions, 46 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c6776909747..07030be0ef2 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -1201,11 +1201,8 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) | |||
1201 | return -EIO; | 1201 | return -EIO; |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | 1204 | if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { |
1205 | STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | 1205 | SBP2_INFO("Error querying logins to SBP-2 device - failed"); |
1206 | STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | ||
1207 | |||
1208 | SBP2_INFO("Error querying logins to SBP-2 device - timed out"); | ||
1209 | return -EIO; | 1206 | return -EIO; |
1210 | } | 1207 | } |
1211 | 1208 | ||
@@ -1298,18 +1295,12 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) | |||
1298 | * Sanity. Make sure status returned matches login orb. | 1295 | * Sanity. Make sure status returned matches login orb. |
1299 | */ | 1296 | */ |
1300 | if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) { | 1297 | if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) { |
1301 | SBP2_ERR("Error logging into SBP-2 device - login timed-out"); | 1298 | SBP2_ERR("Error logging into SBP-2 device - timed out"); |
1302 | return -EIO; | 1299 | return -EIO; |
1303 | } | 1300 | } |
1304 | 1301 | ||
1305 | /* | 1302 | if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { |
1306 | * Check status | 1303 | SBP2_ERR("Error logging into SBP-2 device - failed"); |
1307 | */ | ||
1308 | if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | ||
1309 | STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | ||
1310 | STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | ||
1311 | |||
1312 | SBP2_ERR("Error logging into SBP-2 device - login failed"); | ||
1313 | return -EIO; | 1304 | return -EIO; |
1314 | } | 1305 | } |
1315 | 1306 | ||
@@ -1333,9 +1324,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) | |||
1333 | scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL; | 1324 | scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL; |
1334 | 1325 | ||
1335 | SBP2_INFO("Logged into SBP-2 device"); | 1326 | SBP2_INFO("Logged into SBP-2 device"); |
1336 | |||
1337 | return 0; | 1327 | return 0; |
1338 | |||
1339 | } | 1328 | } |
1340 | 1329 | ||
1341 | /* | 1330 | /* |
@@ -1466,25 +1455,17 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) | |||
1466 | * Sanity. Make sure status returned matches reconnect orb. | 1455 | * Sanity. Make sure status returned matches reconnect orb. |
1467 | */ | 1456 | */ |
1468 | if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) { | 1457 | if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) { |
1469 | SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out"); | 1458 | SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); |
1470 | return -EIO; | 1459 | return -EIO; |
1471 | } | 1460 | } |
1472 | 1461 | ||
1473 | /* | 1462 | if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { |
1474 | * Check status | 1463 | SBP2_ERR("Error reconnecting to SBP-2 device - failed"); |
1475 | */ | ||
1476 | if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | ||
1477 | STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | ||
1478 | STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | ||
1479 | |||
1480 | SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed"); | ||
1481 | return -EIO; | 1464 | return -EIO; |
1482 | } | 1465 | } |
1483 | 1466 | ||
1484 | HPSB_DEBUG("Reconnected to SBP-2 device"); | 1467 | HPSB_DEBUG("Reconnected to SBP-2 device"); |
1485 | |||
1486 | return 0; | 1468 | return 0; |
1487 | |||
1488 | } | 1469 | } |
1489 | 1470 | ||
1490 | /* | 1471 | /* |
@@ -2115,18 +2096,19 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
2115 | 2096 | ||
2116 | sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); | 2097 | sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); |
2117 | 2098 | ||
2118 | if (!host) { | 2099 | if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) { |
2100 | SBP2_ERR("Wrong size of status block"); | ||
2101 | return RCODE_ADDRESS_ERROR; | ||
2102 | } | ||
2103 | if (unlikely(!host)) { | ||
2119 | SBP2_ERR("host is NULL - this is bad!"); | 2104 | SBP2_ERR("host is NULL - this is bad!"); |
2120 | return RCODE_ADDRESS_ERROR; | 2105 | return RCODE_ADDRESS_ERROR; |
2121 | } | 2106 | } |
2122 | |||
2123 | hi = hpsb_get_hostinfo(&sbp2_highlevel, host); | 2107 | hi = hpsb_get_hostinfo(&sbp2_highlevel, host); |
2124 | 2108 | if (unlikely(!hi)) { | |
2125 | if (!hi) { | ||
2126 | SBP2_ERR("host info is NULL - this is bad!"); | 2109 | SBP2_ERR("host info is NULL - this is bad!"); |
2127 | return RCODE_ADDRESS_ERROR; | 2110 | return RCODE_ADDRESS_ERROR; |
2128 | } | 2111 | } |
2129 | |||
2130 | /* | 2112 | /* |
2131 | * Find our scsi_id structure by looking at the status fifo address | 2113 | * Find our scsi_id structure by looking at the status fifo address |
2132 | * written to by the sbp2 device. | 2114 | * written to by the sbp2 device. |
@@ -2138,8 +2120,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
2138 | break; | 2120 | break; |
2139 | } | 2121 | } |
2140 | } | 2122 | } |
2141 | 2123 | if (unlikely(!scsi_id)) { | |
2142 | if (!scsi_id) { | ||
2143 | SBP2_ERR("scsi_id is NULL - device is gone?"); | 2124 | SBP2_ERR("scsi_id is NULL - device is gone?"); |
2144 | return RCODE_ADDRESS_ERROR; | 2125 | return RCODE_ADDRESS_ERROR; |
2145 | } | 2126 | } |
@@ -2156,12 +2137,14 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
2156 | sbp2util_be32_to_cpu_buffer(sb, 8); | 2137 | sbp2util_be32_to_cpu_buffer(sb, 8); |
2157 | 2138 | ||
2158 | /* | 2139 | /* |
2159 | * Handle command ORB status here if necessary. First, need to match | 2140 | * Ignore unsolicited status. Handle command ORB status. |
2160 | * status with command. | ||
2161 | */ | 2141 | */ |
2162 | command = sbp2util_find_command_for_orb(scsi_id, sb->ORB_offset_lo); | 2142 | if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2)) |
2143 | command = NULL; | ||
2144 | else | ||
2145 | command = sbp2util_find_command_for_orb(scsi_id, | ||
2146 | sb->ORB_offset_lo); | ||
2163 | if (command) { | 2147 | if (command) { |
2164 | |||
2165 | SBP2_DEBUG("Found status for command ORB"); | 2148 | SBP2_DEBUG("Found status for command ORB"); |
2166 | pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, | 2149 | pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, |
2167 | sizeof(struct sbp2_command_orb), | 2150 | sizeof(struct sbp2_command_orb), |
@@ -2177,16 +2160,23 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
2177 | * Matched status with command, now grab scsi command pointers | 2160 | * Matched status with command, now grab scsi command pointers |
2178 | * and check status. | 2161 | * and check status. |
2179 | */ | 2162 | */ |
2163 | /* | ||
2164 | * FIXME: If the src field in the status is 1, the ORB DMA must | ||
2165 | * not be reused until status for a subsequent ORB is received. | ||
2166 | */ | ||
2180 | SCpnt = command->Current_SCpnt; | 2167 | SCpnt = command->Current_SCpnt; |
2181 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 2168 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); |
2182 | sbp2util_mark_command_completed(scsi_id, command); | 2169 | sbp2util_mark_command_completed(scsi_id, command); |
2183 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 2170 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); |
2184 | 2171 | ||
2185 | if (SCpnt) { | 2172 | if (SCpnt) { |
2173 | if (STATUS_TEST_RS(sb->ORB_offset_hi_misc)) | ||
2174 | scsi_status = | ||
2175 | SBP2_SCSI_STATUS_COMMAND_TERMINATED; | ||
2186 | /* | 2176 | /* |
2187 | * See if the target stored any scsi status information. | 2177 | * See if the target stored any scsi status information. |
2188 | */ | 2178 | */ |
2189 | if (STATUS_GET_LENGTH(sb->ORB_offset_hi_misc) > 1) { | 2179 | if (STATUS_GET_LEN(sb->ORB_offset_hi_misc) > 1) { |
2190 | SBP2_DEBUG("CHECK CONDITION"); | 2180 | SBP2_DEBUG("CHECK CONDITION"); |
2191 | scsi_status = sbp2_status_to_sense_data( | 2181 | scsi_status = sbp2_status_to_sense_data( |
2192 | (unchar *)sb, SCpnt->sense_buffer); | 2182 | (unchar *)sb, SCpnt->sense_buffer); |
@@ -2196,7 +2186,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
2196 | * Check to see if the dead bit is set. If so, we'll | 2186 | * Check to see if the dead bit is set. If so, we'll |
2197 | * have to initiate a fetch agent reset. | 2187 | * have to initiate a fetch agent reset. |
2198 | */ | 2188 | */ |
2199 | if (STATUS_GET_DEAD_BIT(sb->ORB_offset_hi_misc)) { | 2189 | if (STATUS_TEST_D(sb->ORB_offset_hi_misc)) { |
2200 | SBP2_DEBUG("Dead bit set - " | 2190 | SBP2_DEBUG("Dead bit set - " |
2201 | "initiating fetch agent reset"); | 2191 | "initiating fetch agent reset"); |
2202 | sbp2_agent_reset(scsi_id, 0); | 2192 | sbp2_agent_reset(scsi_id, 0); |
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index b17016b7cfc..34e3d37fc79 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
@@ -180,12 +180,14 @@ struct sbp2_unrestricted_page_table { | |||
180 | 180 | ||
181 | #define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff | 181 | #define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff |
182 | 182 | ||
183 | #define STATUS_GET_ORB_OFFSET_HI(value) (value & 0xffff) | 183 | #define STATUS_GET_SRC(value) (((value) >> 30) & 0x3) |
184 | #define STATUS_GET_SBP_STATUS(value) ((value >> 16) & 0xff) | 184 | #define STATUS_GET_LEN(value) (((value) >> 24) & 0x7) |
185 | #define STATUS_GET_LENGTH(value) ((value >> 24) & 0x7) | 185 | #define STATUS_GET_ORB_OFFSET_HI(value) ((value) & 0x0000ffff) |
186 | #define STATUS_GET_DEAD_BIT(value) ((value >> 27) & 0x1) | 186 | #define STATUS_TEST_D(value) ((value) & 0x08000000) |
187 | #define STATUS_GET_RESP(value) ((value >> 28) & 0x3) | 187 | /* test 'resp' | 'sbp2_status' */ |
188 | #define STATUS_GET_SRC(value) ((value >> 30) & 0x3) | 188 | #define STATUS_TEST_RS(value) ((value) & 0x30ff0000) |
189 | /* test 'resp' | 'dead' | 'sbp2_status' */ | ||
190 | #define STATUS_TEST_RDS(value) ((value) & 0x38ff0000) | ||
189 | 191 | ||
190 | struct sbp2_status_block { | 192 | struct sbp2_status_block { |
191 | u32 ORB_offset_hi_misc; | 193 | u32 ORB_offset_hi_misc; |