61
61
#define SSIF_IPMI_REQUEST 2
62
62
#define SSIF_IPMI_MULTI_PART_REQUEST_START 6
63
63
#define SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE 7
64
+ #define SSIF_IPMI_MULTI_PART_REQUEST_END 8
64
65
#define SSIF_IPMI_RESPONSE 3
65
66
#define SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE 9
66
67
@@ -272,6 +273,7 @@ struct ssif_info {
272
273
/* Info from SSIF cmd */
273
274
unsigned char max_xmit_msg_size ;
274
275
unsigned char max_recv_msg_size ;
276
+ bool cmd8_works ; /* See test_multipart_messages() for details. */
275
277
unsigned int multi_support ;
276
278
int supports_pec ;
277
279
@@ -885,32 +887,33 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
885
887
* in the SSIF_MULTI_n_PART case in the probe function
886
888
* for details on the intricacies of this.
887
889
*/
888
- int left ;
890
+ int left , to_write ;
889
891
unsigned char * data_to_send ;
892
+ unsigned char cmd ;
890
893
891
894
ssif_inc_stat (ssif_info , sent_messages_parts );
892
895
893
896
left = ssif_info -> multi_len - ssif_info -> multi_pos ;
894
- if (left > 32 )
895
- left = 32 ;
897
+ to_write = left ;
898
+ if (to_write > 32 )
899
+ to_write = 32 ;
896
900
/* Length byte. */
897
- ssif_info -> multi_data [ssif_info -> multi_pos ] = left ;
901
+ ssif_info -> multi_data [ssif_info -> multi_pos ] = to_write ;
898
902
data_to_send = ssif_info -> multi_data + ssif_info -> multi_pos ;
899
- ssif_info -> multi_pos += left ;
900
- if ( left < 32 )
901
- /*
902
- * Write is finished. Note that we must end
903
- * with a write of less than 32 bytes to
904
- * complete the transaction, even if it is
905
- * zero bytes.
906
- */
903
+ ssif_info -> multi_pos += to_write ;
904
+ cmd = SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE ;
905
+ if ( ssif_info -> cmd8_works ) {
906
+ if ( left == to_write ) {
907
+ cmd = SSIF_IPMI_MULTI_PART_REQUEST_END ;
908
+ ssif_info -> multi_data = NULL ;
909
+ }
910
+ } else if ( to_write < 32 ) {
907
911
ssif_info -> multi_data = NULL ;
912
+ }
908
913
909
914
rv = ssif_i2c_send (ssif_info , msg_written_handler ,
910
- I2C_SMBUS_WRITE ,
911
- SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE ,
912
- data_to_send ,
913
- I2C_SMBUS_BLOCK_DATA );
915
+ I2C_SMBUS_WRITE , cmd ,
916
+ data_to_send , I2C_SMBUS_BLOCK_DATA );
914
917
if (rv < 0 ) {
915
918
/* request failed, just return the error. */
916
919
ssif_inc_stat (ssif_info , send_errors );
@@ -1242,6 +1245,24 @@ static int ssif_remove(struct i2c_client *client)
1242
1245
return 0 ;
1243
1246
}
1244
1247
1248
+ static int read_response (struct i2c_client * client , unsigned char * resp )
1249
+ {
1250
+ int ret = - ENODEV , retry_cnt = SSIF_RECV_RETRIES ;
1251
+
1252
+ while (retry_cnt > 0 ) {
1253
+ ret = i2c_smbus_read_block_data (client , SSIF_IPMI_RESPONSE ,
1254
+ resp );
1255
+ if (ret > 0 )
1256
+ break ;
1257
+ msleep (SSIF_MSG_MSEC );
1258
+ retry_cnt -- ;
1259
+ if (retry_cnt <= 0 )
1260
+ break ;
1261
+ }
1262
+
1263
+ return ret ;
1264
+ }
1265
+
1245
1266
static int do_cmd (struct i2c_client * client , int len , unsigned char * msg ,
1246
1267
int * resp_len , unsigned char * resp )
1247
1268
{
@@ -1258,26 +1279,16 @@ static int do_cmd(struct i2c_client *client, int len, unsigned char *msg,
1258
1279
return - ENODEV ;
1259
1280
}
1260
1281
1261
- ret = - ENODEV ;
1262
- retry_cnt = SSIF_RECV_RETRIES ;
1263
- while (retry_cnt > 0 ) {
1264
- ret = i2c_smbus_read_block_data (client , SSIF_IPMI_RESPONSE ,
1265
- resp );
1266
- if (ret > 0 )
1267
- break ;
1268
- msleep (SSIF_MSG_MSEC );
1269
- retry_cnt -- ;
1270
- if (retry_cnt <= 0 )
1271
- break ;
1272
- }
1273
-
1282
+ ret = read_response (client , resp );
1274
1283
if (ret > 0 ) {
1275
1284
/* Validate that the response is correct. */
1276
1285
if (ret < 3 ||
1277
1286
(resp [0 ] != (msg [0 ] | (1 << 2 ))) ||
1278
1287
(resp [1 ] != msg [1 ]))
1279
1288
ret = - EINVAL ;
1280
- else {
1289
+ else if (ret > IPMI_MAX_MSG_LENGTH ) {
1290
+ ret = - E2BIG ;
1291
+ } else {
1281
1292
* resp_len = ret ;
1282
1293
ret = 0 ;
1283
1294
}
@@ -1389,6 +1400,121 @@ static int find_slave_address(struct i2c_client *client, int slave_addr)
1389
1400
return slave_addr ;
1390
1401
}
1391
1402
1403
+ static int start_multipart_test (struct i2c_client * client ,
1404
+ unsigned char * msg , bool do_middle )
1405
+ {
1406
+ int retry_cnt = SSIF_SEND_RETRIES , ret ;
1407
+
1408
+ retry_write :
1409
+ ret = i2c_smbus_write_block_data (client ,
1410
+ SSIF_IPMI_MULTI_PART_REQUEST_START ,
1411
+ 32 , msg );
1412
+ if (ret ) {
1413
+ retry_cnt -- ;
1414
+ if (retry_cnt > 0 )
1415
+ goto retry_write ;
1416
+ dev_err (& client -> dev , "Could not write multi-part start, though the BMC said it could handle it. Just limit sends to one part.\n" );
1417
+ return ret ;
1418
+ }
1419
+
1420
+ if (!do_middle )
1421
+ return 0 ;
1422
+
1423
+ ret = i2c_smbus_write_block_data (client ,
1424
+ SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE ,
1425
+ 32 , msg + 32 );
1426
+ if (ret ) {
1427
+ dev_err (& client -> dev , "Could not write multi-part middle, though the BMC said it could handle it. Just limit sends to one part.\n" );
1428
+ return ret ;
1429
+ }
1430
+
1431
+ return 0 ;
1432
+ }
1433
+
1434
+ static void test_multipart_messages (struct i2c_client * client ,
1435
+ struct ssif_info * ssif_info ,
1436
+ unsigned char * resp )
1437
+ {
1438
+ unsigned char msg [65 ];
1439
+ int ret ;
1440
+ bool do_middle ;
1441
+
1442
+ if (ssif_info -> max_xmit_msg_size <= 32 )
1443
+ return ;
1444
+
1445
+ do_middle = ssif_info -> max_xmit_msg_size > 63 ;
1446
+
1447
+ memset (msg , 0 , sizeof (msg ));
1448
+ msg [0 ] = IPMI_NETFN_APP_REQUEST << 2 ;
1449
+ msg [1 ] = IPMI_GET_DEVICE_ID_CMD ;
1450
+
1451
+ /*
1452
+ * The specification is all messed up dealing with sending
1453
+ * multi-part messages. Per what the specification says, it
1454
+ * is impossible to send a message that is a multiple of 32
1455
+ * bytes, except for 32 itself. It talks about a "start"
1456
+ * transaction (cmd=6) that must be 32 bytes, "middle"
1457
+ * transaction (cmd=7) that must be 32 bytes, and an "end"
1458
+ * transaction. The "end" transaction is shown as cmd=7 in
1459
+ * the text, but if that's the case there is no way to
1460
+ * differentiate between a middle and end part except the
1461
+ * length being less than 32. But there is a table at the far
1462
+ * end of the section (that I had never noticed until someone
1463
+ * pointed it out to me) that mentions it as cmd=8.
1464
+ *
1465
+ * After some thought, I think the example is wrong and the
1466
+ * end transaction should be cmd=8. But some systems don't
1467
+ * implement cmd=8, they use a zero-length end transaction,
1468
+ * even though that violates the SMBus specification.
1469
+ *
1470
+ * So, to work around this, this code tests if cmd=8 works.
1471
+ * If it does, then we use that. If not, it tests zero-
1472
+ * byte end transactions. If that works, good. If not,
1473
+ * we only allow 63-byte transactions max.
1474
+ */
1475
+
1476
+ ret = start_multipart_test (client , msg , do_middle );
1477
+ if (ret )
1478
+ goto out_no_multi_part ;
1479
+
1480
+ ret = i2c_smbus_write_block_data (client ,
1481
+ SSIF_IPMI_MULTI_PART_REQUEST_END ,
1482
+ 1 , msg + 64 );
1483
+
1484
+ if (!ret )
1485
+ ret = read_response (client , resp );
1486
+
1487
+ if (ret > 0 ) {
1488
+ /* End transactions work, we are good. */
1489
+ ssif_info -> cmd8_works = true;
1490
+ return ;
1491
+ }
1492
+
1493
+ ret = start_multipart_test (client , msg , do_middle );
1494
+ if (ret ) {
1495
+ dev_err (& client -> dev , "Second multipart test failed.\n" );
1496
+ goto out_no_multi_part ;
1497
+ }
1498
+
1499
+ ret = i2c_smbus_write_block_data (client ,
1500
+ SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE ,
1501
+ 0 , msg + 64 );
1502
+ if (!ret )
1503
+ ret = read_response (client , resp );
1504
+ if (ret > 0 )
1505
+ /* Zero-size end parts work, use those. */
1506
+ return ;
1507
+
1508
+ /* Limit to 63 bytes and use a short middle command to mark the end. */
1509
+ if (ssif_info -> max_xmit_msg_size > 63 )
1510
+ ssif_info -> max_xmit_msg_size = 63 ;
1511
+ return ;
1512
+
1513
+ out_no_multi_part :
1514
+ ssif_info -> max_xmit_msg_size = 32 ;
1515
+ return ;
1516
+ }
1517
+
1392
1518
/*
1393
1519
* Global enables we care about.
1394
1520
*/
@@ -1475,26 +1601,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
1475
1601
break ;
1476
1602
1477
1603
case SSIF_MULTI_n_PART :
1478
- /*
1479
- * The specification is rather confusing at
1480
- * this point, but I think I understand what
1481
- * is meant. At least I have a workable
1482
- * solution. With multi-part messages, you
1483
- * cannot send a message that is a multiple of
1484
- * 32-bytes in length, because the start and
1485
- * middle messages are 32-bytes and the end
1486
- * message must be at least one byte. You
1487
- * can't fudge on an extra byte, that would
1488
- * screw up things like fru data writes. So
1489
- * we limit the length to 63 bytes. That way
1490
- * a 32-byte message gets sent as a single
1491
- * part. A larger message will be a 32-byte
1492
- * start and the next message is always going
1493
- * to be 1-31 bytes in length. Not ideal, but
1494
- * it should work.
1495
- */
1496
- if (ssif_info -> max_xmit_msg_size > 63 )
1497
- ssif_info -> max_xmit_msg_size = 63 ;
1604
+ /* We take whatever size given, but do some testing. */
1498
1605
break ;
1499
1606
1500
1607
default :
@@ -1513,6 +1620,8 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
1513
1620
ssif_info -> supports_pec = 0 ;
1514
1621
}
1515
1622
1623
+ test_multipart_messages (client , ssif_info , resp );
1624
+
1516
1625
/* Make sure the NMI timeout is cleared. */
1517
1626
msg [0 ] = IPMI_NETFN_APP_REQUEST << 2 ;
1518
1627
msg [1 ] = IPMI_CLEAR_MSG_FLAGS_CMD ;
0 commit comments