aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-07-23 16:18:00 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-17 13:29:24 -0400
commit6065772d54a3b994b9b5d3df6413ec6a1c8c2ec1 (patch)
treead4eff582622e00443e1a685d8d8a2553412edc0 /drivers/ieee1394
parent3e98eab46d1a482532c653bdb0c006413654d171 (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.c70
-rw-r--r--drivers/ieee1394/sbp2.h14
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
190struct sbp2_status_block { 192struct sbp2_status_block {
191 u32 ORB_offset_hi_misc; 193 u32 ORB_offset_hi_misc;