@@ -653,6 +653,11 @@ static int is_ipmb_bcast_addr(struct ipmi_addr *addr)
653
653
return addr -> addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE ;
654
654
}
655
655
656
+ static int is_ipmb_direct_addr (struct ipmi_addr * addr )
657
+ {
658
+ return addr -> addr_type == IPMI_IPMB_DIRECT_ADDR_TYPE ;
659
+ }
660
+
656
661
static void free_recv_msg_list (struct list_head * q )
657
662
{
658
663
struct ipmi_recv_msg * msg , * msg2 ;
@@ -805,6 +810,17 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
805
810
&& (ipmb_addr1 -> lun == ipmb_addr2 -> lun ));
806
811
}
807
812
813
+ if (is_ipmb_direct_addr (addr1 )) {
814
+ struct ipmi_ipmb_direct_addr * daddr1
815
+ = (struct ipmi_ipmb_direct_addr * ) addr1 ;
816
+ struct ipmi_ipmb_direct_addr * daddr2
817
+ = (struct ipmi_ipmb_direct_addr * ) addr2 ;
818
+
819
+ return daddr1 -> slave_addr == daddr2 -> slave_addr &&
820
+ daddr1 -> rq_lun == daddr2 -> rq_lun &&
821
+ daddr1 -> rs_lun == daddr2 -> rs_lun ;
822
+ }
823
+
808
824
if (is_lan_addr (addr1 )) {
809
825
struct ipmi_lan_addr * lan_addr1
810
826
= (struct ipmi_lan_addr * ) addr1 ;
@@ -843,6 +859,23 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
843
859
return 0 ;
844
860
}
845
861
862
+ if (is_ipmb_direct_addr (addr )) {
863
+ struct ipmi_ipmb_direct_addr * daddr = (void * ) addr ;
864
+
865
+ if (addr -> channel != 0 )
866
+ return - EINVAL ;
867
+ if (len < sizeof (struct ipmi_ipmb_direct_addr ))
868
+ return - EINVAL ;
869
+
870
+ if (daddr -> slave_addr & 0x01 )
871
+ return - EINVAL ;
872
+ if (daddr -> rq_lun >= 4 )
873
+ return - EINVAL ;
874
+ if (daddr -> rs_lun >= 4 )
875
+ return - EINVAL ;
876
+ return 0 ;
877
+ }
878
+
846
879
if (is_lan_addr (addr )) {
847
880
if (len < sizeof (struct ipmi_lan_addr ))
848
881
return - EINVAL ;
@@ -862,6 +895,9 @@ unsigned int ipmi_addr_length(int addr_type)
862
895
|| (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE ))
863
896
return sizeof (struct ipmi_ipmb_addr );
864
897
898
+ if (addr_type == IPMI_IPMB_DIRECT_ADDR_TYPE )
899
+ return sizeof (struct ipmi_ipmb_direct_addr );
900
+
865
901
if (addr_type == IPMI_LAN_ADDR_TYPE )
866
902
return sizeof (struct ipmi_lan_addr );
867
903
@@ -2052,6 +2088,58 @@ static int i_ipmi_req_ipmb(struct ipmi_smi *intf,
2052
2088
return rv ;
2053
2089
}
2054
2090
2091
+ static int i_ipmi_req_ipmb_direct (struct ipmi_smi * intf ,
2092
+ struct ipmi_addr * addr ,
2093
+ long msgid ,
2094
+ struct kernel_ipmi_msg * msg ,
2095
+ struct ipmi_smi_msg * smi_msg ,
2096
+ struct ipmi_recv_msg * recv_msg ,
2097
+ unsigned char source_lun )
2098
+ {
2099
+ struct ipmi_ipmb_direct_addr * daddr ;
2100
+ bool is_cmd = !(recv_msg -> msg .netfn & 0x1 );
2101
+
2102
+ if (!(intf -> handlers -> flags & IPMI_SMI_CAN_HANDLE_IPMB_DIRECT ))
2103
+ return - EAFNOSUPPORT ;
2104
+
2105
+ /* Responses must have a completion code. */
2106
+ if (!is_cmd && msg -> data_len < 1 ) {
2107
+ ipmi_inc_stat (intf , sent_invalid_commands );
2108
+ return - EINVAL ;
2109
+ }
2110
+
2111
+ if ((msg -> data_len + 4 ) > IPMI_MAX_MSG_LENGTH ) {
2112
+ ipmi_inc_stat (intf , sent_invalid_commands );
2113
+ return - EMSGSIZE ;
2114
+ }
2115
+
2116
+ daddr = (struct ipmi_ipmb_direct_addr * ) addr ;
2117
+ if (daddr -> rq_lun > 3 || daddr -> rs_lun > 3 ) {
2118
+ ipmi_inc_stat (intf , sent_invalid_commands );
2119
+ return - EINVAL ;
2120
+ }
2121
+
2122
+ smi_msg -> type = IPMI_SMI_MSG_TYPE_IPMB_DIRECT ;
2123
+ smi_msg -> msgid = msgid ;
2124
+
2125
+ if (is_cmd ) {
2126
+ smi_msg -> data [0 ] = msg -> netfn << 2 | daddr -> rs_lun ;
2127
+ smi_msg -> data [2 ] = recv_msg -> msgid << 2 | daddr -> rq_lun ;
2128
+ } else {
2129
+ smi_msg -> data [0 ] = msg -> netfn << 2 | daddr -> rq_lun ;
2130
+ smi_msg -> data [2 ] = recv_msg -> msgid << 2 | daddr -> rs_lun ;
2131
+ }
2132
+ smi_msg -> data [1 ] = daddr -> slave_addr ;
2133
+ smi_msg -> data [3 ] = msg -> cmd ;
2134
+
2135
+ memcpy (smi_msg -> data + 4 , msg -> data , msg -> data_len );
2136
+ smi_msg -> data_size = msg -> data_len + 4 ;
2137
+
2138
+ smi_msg -> user_data = recv_msg ;
2139
+
2140
+ return 0 ;
2141
+ }
2142
+
2055
2143
static int i_ipmi_req_lan (struct ipmi_smi * intf ,
2056
2144
struct ipmi_addr * addr ,
2057
2145
long msgid ,
@@ -2241,6 +2329,9 @@ static int i_ipmi_request(struct ipmi_user *user,
2241
2329
rv = i_ipmi_req_ipmb (intf , addr , msgid , msg , smi_msg , recv_msg ,
2242
2330
source_address , source_lun ,
2243
2331
retries , retry_time_ms );
2332
+ } else if (is_ipmb_direct_addr (addr )) {
2333
+ rv = i_ipmi_req_ipmb_direct (intf , addr , msgid , msg , smi_msg ,
2334
+ recv_msg , source_lun );
2244
2335
} else if (is_lan_addr (addr )) {
2245
2336
rv = i_ipmi_req_lan (intf , addr , msgid , msg , smi_msg , recv_msg ,
2246
2337
source_lun , retries , retry_time_ms );
@@ -3802,6 +3893,123 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
3802
3893
return rv ;
3803
3894
}
3804
3895
3896
+ static int handle_ipmb_direct_rcv_cmd (struct ipmi_smi * intf ,
3897
+ struct ipmi_smi_msg * msg )
3898
+ {
3899
+ struct cmd_rcvr * rcvr ;
3900
+ int rv = 0 ;
3901
+ struct ipmi_user * user = NULL ;
3902
+ struct ipmi_ipmb_direct_addr * daddr ;
3903
+ struct ipmi_recv_msg * recv_msg ;
3904
+ unsigned char netfn = msg -> rsp [0 ] >> 2 ;
3905
+ unsigned char cmd = msg -> rsp [3 ];
3906
+
3907
+ rcu_read_lock ();
3908
+ /* We always use channel 0 for direct messages. */
3909
+ rcvr = find_cmd_rcvr (intf , netfn , cmd , 0 );
3910
+ if (rcvr ) {
3911
+ user = rcvr -> user ;
3912
+ kref_get (& user -> refcount );
3913
+ } else
3914
+ user = NULL ;
3915
+ rcu_read_unlock ();
3916
+
3917
+ if (user == NULL ) {
3918
+ /* We didn't find a user, deliver an error response. */
3919
+ ipmi_inc_stat (intf , unhandled_commands );
3920
+
3921
+ msg -> data [0 ] = ((netfn + 1 ) << 2 ) | (msg -> rsp [4 ] & 0x3 );
3922
+ msg -> data [1 ] = msg -> rsp [2 ];
3923
+ msg -> data [2 ] = msg -> rsp [4 ] & ~0x3 ;
3924
+ msg -> data [3 ] = cmd ;
3925
+ msg -> data [4 ] = IPMI_INVALID_CMD_COMPLETION_CODE ;
3926
+ msg -> data_size = 5 ;
3927
+
3928
+ rcu_read_lock ();
3929
+ if (!intf -> in_shutdown ) {
3930
+ smi_send (intf , intf -> handlers , msg , 0 );
3931
+ /*
3932
+ * We used the message, so return the value
3933
+ * that causes it to not be freed or
3934
+ * queued.
3935
+ */
3936
+ rv = -1 ;
3937
+ }
3938
+ rcu_read_unlock ();
3939
+ } else {
3940
+ recv_msg = ipmi_alloc_recv_msg ();
3941
+ if (!recv_msg ) {
3942
+ /*
3943
+ * We couldn't allocate memory for the
3944
+ * message, so requeue it for handling
3945
+ * later.
3946
+ */
3947
+ rv = 1 ;
3948
+ kref_put (& user -> refcount , free_user );
3949
+ } else {
3950
+ /* Extract the source address from the data. */
3951
+ daddr = (struct ipmi_ipmb_direct_addr * )& recv_msg -> addr ;
3952
+ daddr -> addr_type = IPMI_IPMB_DIRECT_ADDR_TYPE ;
3953
+ daddr -> channel = 0 ;
3954
+ daddr -> slave_addr = msg -> rsp [1 ];
3955
+ daddr -> rs_lun = msg -> rsp [0 ] & 3 ;
3956
+ daddr -> rq_lun = msg -> rsp [2 ] & 3 ;
3957
+
3958
+ /*
3959
+ * Extract the rest of the message information
3960
+ * from the IPMB header.
3961
+ */
3962
+ recv_msg -> user = user ;
3963
+ recv_msg -> recv_type = IPMI_CMD_RECV_TYPE ;
3964
+ recv_msg -> msgid = (msg -> rsp [2 ] >> 2 );
3965
+ recv_msg -> msg .netfn = msg -> rsp [0 ] >> 2 ;
3966
+ recv_msg -> msg .cmd = msg -> rsp [3 ];
3967
+ recv_msg -> msg .data = recv_msg -> msg_data ;
3968
+
3969
+ recv_msg -> msg .data_len = msg -> rsp_size - 4 ;
3970
+ memcpy (recv_msg -> msg_data , msg -> rsp + 4 ,
3971
+ msg -> rsp_size - 4 );
3972
+ if (deliver_response (intf , recv_msg ))
3973
+ ipmi_inc_stat (intf , unhandled_commands );
3974
+ else
3975
+ ipmi_inc_stat (intf , handled_commands );
3976
+ }
3977
+ }
3978
+
3979
+ return rv ;
3980
+ }
3981
+
3982
+ static int handle_ipmb_direct_rcv_rsp (struct ipmi_smi * intf ,
3983
+ struct ipmi_smi_msg * msg )
3984
+ {
3985
+ struct ipmi_recv_msg * recv_msg ;
3986
+ struct ipmi_ipmb_direct_addr * daddr ;
3987
+
3988
+ recv_msg = (struct ipmi_recv_msg * ) msg -> user_data ;
3989
+ if (recv_msg == NULL ) {
3990
+ dev_warn (intf -> si_dev ,
3991
+ "IPMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n" );
3992
+ return 0 ;
3993
+ }
3994
+
3995
+ recv_msg -> recv_type = IPMI_RESPONSE_RECV_TYPE ;
3996
+ recv_msg -> msgid = msg -> msgid ;
3997
+ daddr = (struct ipmi_ipmb_direct_addr * ) & recv_msg -> addr ;
3998
+ daddr -> addr_type = IPMI_IPMB_DIRECT_ADDR_TYPE ;
3999
+ daddr -> channel = 0 ;
4000
+ daddr -> slave_addr = msg -> rsp [1 ];
4001
+ daddr -> rq_lun = msg -> rsp [0 ] & 3 ;
4002
+ daddr -> rs_lun = msg -> rsp [2 ] & 3 ;
4003
+ recv_msg -> msg .netfn = msg -> rsp [0 ] >> 2 ;
4004
+ recv_msg -> msg .cmd = msg -> rsp [3 ];
4005
+ memcpy (recv_msg -> msg_data , & msg -> rsp [4 ], msg -> rsp_size - 4 );
4006
+ recv_msg -> msg .data = recv_msg -> msg_data ;
4007
+ recv_msg -> msg .data_len = msg -> rsp_size - 4 ;
4008
+ deliver_local_response (intf , recv_msg );
4009
+
4010
+ return 0 ;
4011
+ }
4012
+
3805
4013
static int handle_lan_get_msg_rsp (struct ipmi_smi * intf ,
3806
4014
struct ipmi_smi_msg * msg )
3807
4015
{
@@ -4227,18 +4435,40 @@ static int handle_bmc_rsp(struct ipmi_smi *intf,
4227
4435
static int handle_one_recv_msg (struct ipmi_smi * intf ,
4228
4436
struct ipmi_smi_msg * msg )
4229
4437
{
4230
- int requeue ;
4438
+ int requeue = 0 ;
4231
4439
int chan ;
4440
+ unsigned char cc ;
4441
+ bool is_cmd = !((msg -> rsp [0 ] >> 2 ) & 1 );
4232
4442
4233
4443
pr_debug ("Recv: %*ph\n" , msg -> rsp_size , msg -> rsp );
4234
4444
4235
- if ((msg -> data_size >= 2 )
4445
+ if (msg -> rsp_size < 2 ) {
4446
+ /* Message is too small to be correct. */
4447
+ dev_warn (intf -> si_dev ,
4448
+ "BMC returned too small a message for netfn %x cmd %x, got %d bytes\n" ,
4449
+ (msg -> data [0 ] >> 2 ) | 1 , msg -> data [1 ], msg -> rsp_size );
4450
+
4451
+ return_unspecified :
4452
+ /* Generate an error response for the message. */
4453
+ msg -> rsp [0 ] = msg -> data [0 ] | (1 << 2 );
4454
+ msg -> rsp [1 ] = msg -> data [1 ];
4455
+ msg -> rsp [2 ] = IPMI_ERR_UNSPECIFIED ;
4456
+ msg -> rsp_size = 3 ;
4457
+ } else if (msg -> type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT ) {
4458
+ /* commands must have at least 3 bytes, responses 4. */
4459
+ if (is_cmd && (msg -> rsp_size < 3 )) {
4460
+ ipmi_inc_stat (intf , invalid_commands );
4461
+ goto out ;
4462
+ }
4463
+ if (!is_cmd && (msg -> rsp_size < 4 ))
4464
+ goto return_unspecified ;
4465
+ } else if ((msg -> data_size >= 2 )
4236
4466
&& (msg -> data [0 ] == (IPMI_NETFN_APP_REQUEST << 2 ))
4237
4467
&& (msg -> data [1 ] == IPMI_SEND_MSG_CMD )
4238
4468
&& (msg -> user_data == NULL )) {
4239
4469
4240
4470
if (intf -> in_shutdown )
4241
- goto free_msg ;
4471
+ goto out ;
4242
4472
4243
4473
/*
4244
4474
* This is the local response to a command send, start
@@ -4273,21 +4503,6 @@ static int handle_one_recv_msg(struct ipmi_smi *intf,
4273
4503
} else
4274
4504
/* The message was sent, start the timer. */
4275
4505
intf_start_seq_timer (intf , msg -> msgid );
4276
- free_msg :
4277
- requeue = 0 ;
4278
- goto out ;
4279
-
4280
- } else if (msg -> rsp_size < 2 ) {
4281
- /* Message is too small to be correct. */
4282
- dev_warn (intf -> si_dev ,
4283
- "BMC returned too small a message for netfn %x cmd %x, got %d bytes\n" ,
4284
- (msg -> data [0 ] >> 2 ) | 1 , msg -> data [1 ], msg -> rsp_size );
4285
-
4286
- /* Generate an error response for the message. */
4287
- msg -> rsp [0 ] = msg -> data [0 ] | (1 << 2 );
4288
- msg -> rsp [1 ] = msg -> data [1 ];
4289
- msg -> rsp [2 ] = IPMI_ERR_UNSPECIFIED ;
4290
- msg -> rsp_size = 3 ;
4291
4506
} else if (((msg -> rsp [0 ] >> 2 ) != ((msg -> data [0 ] >> 2 ) | 1 ))
4292
4507
|| (msg -> rsp [1 ] != msg -> data [1 ])) {
4293
4508
/*
@@ -4299,39 +4514,46 @@ static int handle_one_recv_msg(struct ipmi_smi *intf,
4299
4514
(msg -> data [0 ] >> 2 ) | 1 , msg -> data [1 ],
4300
4515
msg -> rsp [0 ] >> 2 , msg -> rsp [1 ]);
4301
4516
4302
- /* Generate an error response for the message. */
4303
- msg -> rsp [0 ] = msg -> data [0 ] | (1 << 2 );
4304
- msg -> rsp [1 ] = msg -> data [1 ];
4305
- msg -> rsp [2 ] = IPMI_ERR_UNSPECIFIED ;
4306
- msg -> rsp_size = 3 ;
4517
+ goto return_unspecified ;
4307
4518
}
4308
4519
4309
- if ((msg -> rsp [0 ] == ((IPMI_NETFN_APP_REQUEST |1 ) << 2 ))
4310
- && (msg -> rsp [1 ] == IPMI_SEND_MSG_CMD )
4311
- && (msg -> user_data != NULL )) {
4520
+ if (msg -> type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT ) {
4521
+ if ((msg -> data [0 ] >> 2 ) & 1 ) {
4522
+ /* It's a response to a sent response. */
4523
+ chan = 0 ;
4524
+ cc = msg -> rsp [4 ];
4525
+ goto process_response_response ;
4526
+ }
4527
+ if (is_cmd )
4528
+ requeue = handle_ipmb_direct_rcv_cmd (intf , msg );
4529
+ else
4530
+ requeue = handle_ipmb_direct_rcv_rsp (intf , msg );
4531
+ } else if ((msg -> rsp [0 ] == ((IPMI_NETFN_APP_REQUEST |1 ) << 2 ))
4532
+ && (msg -> rsp [1 ] == IPMI_SEND_MSG_CMD )
4533
+ && (msg -> user_data != NULL )) {
4312
4534
/*
4313
4535
* It's a response to a response we sent. For this we
4314
4536
* deliver a send message response to the user.
4315
4537
*/
4316
- struct ipmi_recv_msg * recv_msg = msg -> user_data ;
4317
-
4318
- requeue = 0 ;
4319
- if (msg -> rsp_size < 2 )
4320
- /* Message is too small to be correct. */
4321
- goto out ;
4538
+ struct ipmi_recv_msg * recv_msg ;
4322
4539
4323
4540
chan = msg -> data [2 ] & 0x0f ;
4324
4541
if (chan >= IPMI_MAX_CHANNELS )
4325
4542
/* Invalid channel number */
4326
4543
goto out ;
4544
+ cc = msg -> rsp [2 ];
4327
4545
4546
+ process_response_response :
4547
+ recv_msg = msg -> user_data ;
4548
+
4549
+ requeue = 0 ;
4328
4550
if (!recv_msg )
4329
4551
goto out ;
4330
4552
4331
4553
recv_msg -> recv_type = IPMI_RESPONSE_RESPONSE_TYPE ;
4332
4554
recv_msg -> msg .data = recv_msg -> msg_data ;
4555
+ recv_msg -> msg_data [0 ] = cc ;
4333
4556
recv_msg -> msg .data_len = 1 ;
4334
- recv_msg -> msg_data [0 ] = msg -> rsp [2 ];
4335
4557
deliver_local_response (intf , recv_msg );
4336
4558
} else if ((msg -> rsp [0 ] == ((IPMI_NETFN_APP_REQUEST |1 ) << 2 ))
4337
4559
&& (msg -> rsp [1 ] == IPMI_GET_MSG_CMD )) {
0 commit comments