@@ -940,6 +940,259 @@ static struct mpi3mr_ioc *mpi3mr_bsg_verify_adapter(int ioc_number)
940
940
return NULL ;
941
941
}
942
942
943
+ /**
944
+ * mpi3mr_bsg_refresh_hdb_triggers - Refresh HDB trigger data
945
+ * @mrioc: Adapter instance reference
946
+ * @job: BSG Job pointer
947
+ *
948
+ * This function reads the controller trigger config page as
949
+ * defined by the input page type and refreshes the driver's
950
+ * local trigger information structures with the controller's
951
+ * config page data.
952
+ *
953
+ * Return: 0 on success and proper error codes on failure
954
+ */
955
+ static long
956
+ mpi3mr_bsg_refresh_hdb_triggers (struct mpi3mr_ioc * mrioc ,
957
+ struct bsg_job * job )
958
+ {
959
+ struct mpi3mr_bsg_out_refresh_hdb_triggers refresh_triggers ;
960
+ uint32_t data_out_sz ;
961
+ u8 page_action ;
962
+ long rval = - EINVAL ;
963
+
964
+ data_out_sz = job -> request_payload .payload_len ;
965
+
966
+ if (data_out_sz != sizeof (refresh_triggers )) {
967
+ dprint_bsg_err (mrioc , "%s: invalid size argument\n" ,
968
+ __func__ );
969
+ return rval ;
970
+ }
971
+
972
+ if (mrioc -> unrecoverable ) {
973
+ dprint_bsg_err (mrioc , "%s: unrecoverable controller\n" ,
974
+ __func__ );
975
+ return - EFAULT ;
976
+ }
977
+ if (mrioc -> reset_in_progress ) {
978
+ dprint_bsg_err (mrioc , "%s: reset in progress\n" , __func__ );
979
+ return - EAGAIN ;
980
+ }
981
+
982
+ sg_copy_to_buffer (job -> request_payload .sg_list ,
983
+ job -> request_payload .sg_cnt ,
984
+ & refresh_triggers , sizeof (refresh_triggers ));
985
+
986
+ switch (refresh_triggers .page_type ) {
987
+ case MPI3MR_HDB_REFRESH_TYPE_CURRENT :
988
+ page_action = MPI3_CONFIG_ACTION_READ_CURRENT ;
989
+ break ;
990
+ case MPI3MR_HDB_REFRESH_TYPE_DEFAULT :
991
+ page_action = MPI3_CONFIG_ACTION_READ_DEFAULT ;
992
+ break ;
993
+ case MPI3MR_HDB_HDB_REFRESH_TYPE_PERSISTENT :
994
+ page_action = MPI3_CONFIG_ACTION_READ_PERSISTENT ;
995
+ break ;
996
+ default :
997
+ dprint_bsg_err (mrioc ,
998
+ "%s: unsupported refresh trigger, page_type %d\n" ,
999
+ __func__ , refresh_triggers .page_type );
1000
+ return rval ;
1001
+ }
1002
+ rval = mpi3mr_refresh_trigger (mrioc , page_action );
1003
+
1004
+ return rval ;
1005
+ }
1006
+
1007
+ /**
1008
+ * mpi3mr_bsg_upload_hdb - Upload a specific HDB to user space
1009
+ * @mrioc: Adapter instance reference
1010
+ * @job: BSG Job pointer
1011
+ *
1012
+ * Return: 0 on success and proper error codes on failure
1013
+ */
1014
+ static long mpi3mr_bsg_upload_hdb (struct mpi3mr_ioc * mrioc ,
1015
+ struct bsg_job * job )
1016
+ {
1017
+ struct mpi3mr_bsg_out_upload_hdb upload_hdb ;
1018
+ struct diag_buffer_desc * diag_buffer ;
1019
+ uint32_t data_out_size ;
1020
+ uint32_t data_in_size ;
1021
+
1022
+ data_out_size = job -> request_payload .payload_len ;
1023
+ data_in_size = job -> reply_payload .payload_len ;
1024
+
1025
+ if (data_out_size != sizeof (upload_hdb )) {
1026
+ dprint_bsg_err (mrioc , "%s: invalid size argument\n" ,
1027
+ __func__ );
1028
+ return - EINVAL ;
1029
+ }
1030
+
1031
+ sg_copy_to_buffer (job -> request_payload .sg_list ,
1032
+ job -> request_payload .sg_cnt ,
1033
+ & upload_hdb , sizeof (upload_hdb ));
1034
+
1035
+ if ((!upload_hdb .length ) || (data_in_size != upload_hdb .length )) {
1036
+ dprint_bsg_err (mrioc , "%s: invalid length argument\n" ,
1037
+ __func__ );
1038
+ return - EINVAL ;
1039
+ }
1040
+ diag_buffer = mpi3mr_diag_buffer_for_type (mrioc , upload_hdb .buf_type );
1041
+ if ((!diag_buffer ) || (!diag_buffer -> addr )) {
1042
+ dprint_bsg_err (mrioc , "%s: invalid buffer type %d\n" ,
1043
+ __func__ , upload_hdb .buf_type );
1044
+ return - EINVAL ;
1045
+ }
1046
+
1047
+ if ((diag_buffer -> status != MPI3MR_HDB_BUFSTATUS_RELEASED ) &&
1048
+ (diag_buffer -> status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED )) {
1049
+ dprint_bsg_err (mrioc ,
1050
+ "%s: invalid buffer status %d for type %d\n" ,
1051
+ __func__ , diag_buffer -> status , upload_hdb .buf_type );
1052
+ return - EINVAL ;
1053
+ }
1054
+
1055
+ if ((upload_hdb .start_offset + upload_hdb .length ) > diag_buffer -> size ) {
1056
+ dprint_bsg_err (mrioc ,
1057
+ "%s: invalid start offset %d, length %d for type %d\n" ,
1058
+ __func__ , upload_hdb .start_offset , upload_hdb .length ,
1059
+ upload_hdb .buf_type );
1060
+ return - EINVAL ;
1061
+ }
1062
+ sg_copy_from_buffer (job -> reply_payload .sg_list ,
1063
+ job -> reply_payload .sg_cnt ,
1064
+ (diag_buffer -> addr + upload_hdb .start_offset ),
1065
+ data_in_size );
1066
+ return 0 ;
1067
+ }
1068
+
1069
+ /**
1070
+ * mpi3mr_bsg_repost_hdb - Re-post HDB
1071
+ * @mrioc: Adapter instance reference
1072
+ * @job: BSG job pointer
1073
+ *
1074
+ * This function retrieves the HDB descriptor corresponding to a
1075
+ * given buffer type and if the HDB is in released status then
1076
+ * posts the HDB with the firmware.
1077
+ *
1078
+ * Return: 0 on success and proper error codes on failure
1079
+ */
1080
+ static long mpi3mr_bsg_repost_hdb (struct mpi3mr_ioc * mrioc ,
1081
+ struct bsg_job * job )
1082
+ {
1083
+ struct mpi3mr_bsg_out_repost_hdb repost_hdb ;
1084
+ struct diag_buffer_desc * diag_buffer ;
1085
+ uint32_t data_out_sz ;
1086
+
1087
+ data_out_sz = job -> request_payload .payload_len ;
1088
+
1089
+ if (data_out_sz != sizeof (repost_hdb )) {
1090
+ dprint_bsg_err (mrioc , "%s: invalid size argument\n" ,
1091
+ __func__ );
1092
+ return - EINVAL ;
1093
+ }
1094
+ if (mrioc -> unrecoverable ) {
1095
+ dprint_bsg_err (mrioc , "%s: unrecoverable controller\n" ,
1096
+ __func__ );
1097
+ return - EFAULT ;
1098
+ }
1099
+ if (mrioc -> reset_in_progress ) {
1100
+ dprint_bsg_err (mrioc , "%s: reset in progress\n" , __func__ );
1101
+ return - EAGAIN ;
1102
+ }
1103
+
1104
+ sg_copy_to_buffer (job -> request_payload .sg_list ,
1105
+ job -> request_payload .sg_cnt ,
1106
+ & repost_hdb , sizeof (repost_hdb ));
1107
+
1108
+ diag_buffer = mpi3mr_diag_buffer_for_type (mrioc , repost_hdb .buf_type );
1109
+ if ((!diag_buffer ) || (!diag_buffer -> addr )) {
1110
+ dprint_bsg_err (mrioc , "%s: invalid buffer type %d\n" ,
1111
+ __func__ , repost_hdb .buf_type );
1112
+ return - EINVAL ;
1113
+ }
1114
+
1115
+ if (diag_buffer -> status != MPI3MR_HDB_BUFSTATUS_RELEASED ) {
1116
+ dprint_bsg_err (mrioc ,
1117
+ "%s: invalid buffer status %d for type %d\n" ,
1118
+ __func__ , diag_buffer -> status , repost_hdb .buf_type );
1119
+ return - EINVAL ;
1120
+ }
1121
+
1122
+ if (mpi3mr_issue_diag_buf_post (mrioc , diag_buffer )) {
1123
+ dprint_bsg_err (mrioc , "%s: post failed for type %d\n" ,
1124
+ __func__ , repost_hdb .buf_type );
1125
+ return - EFAULT ;
1126
+ }
1127
+ mpi3mr_set_trigger_data_in_hdb (diag_buffer ,
1128
+ MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN , NULL , 1 );
1129
+
1130
+ return 0 ;
1131
+ }
1132
+
1133
+ /**
1134
+ * mpi3mr_bsg_query_hdb - Handler for query HDB command
1135
+ * @mrioc: Adapter instance reference
1136
+ * @job: BSG job pointer
1137
+ *
1138
+ * This function prepares and copies the host diagnostic buffer
1139
+ * entries to the user buffer.
1140
+ *
1141
+ * Return: 0 on success and proper error codes on failure
1142
+ */
1143
+ static long mpi3mr_bsg_query_hdb (struct mpi3mr_ioc * mrioc ,
1144
+ struct bsg_job * job )
1145
+ {
1146
+ long rval = 0 ;
1147
+ struct mpi3mr_bsg_in_hdb_status * hbd_status ;
1148
+ struct mpi3mr_hdb_entry * hbd_status_entry ;
1149
+ u32 length , min_length ;
1150
+ u8 i ;
1151
+ struct diag_buffer_desc * diag_buffer ;
1152
+ uint32_t data_in_sz = 0 ;
1153
+
1154
+ data_in_sz = job -> request_payload .payload_len ;
1155
+
1156
+ length = (sizeof (* hbd_status ) + ((MPI3MR_MAX_NUM_HDB - 1 ) *
1157
+ sizeof (* hbd_status_entry )));
1158
+ hbd_status = kmalloc (length , GFP_KERNEL );
1159
+ if (!hbd_status )
1160
+ return - ENOMEM ;
1161
+ hbd_status_entry = & hbd_status -> entry [0 ];
1162
+
1163
+ hbd_status -> num_hdb_types = MPI3MR_MAX_NUM_HDB ;
1164
+ for (i = 0 ; i < MPI3MR_MAX_NUM_HDB ; i ++ ) {
1165
+ diag_buffer = & mrioc -> diag_buffers [i ];
1166
+ hbd_status_entry -> buf_type = diag_buffer -> type ;
1167
+ hbd_status_entry -> status = diag_buffer -> status ;
1168
+ hbd_status_entry -> trigger_type = diag_buffer -> trigger_type ;
1169
+ memcpy (& hbd_status_entry -> trigger_data ,
1170
+ & diag_buffer -> trigger_data ,
1171
+ sizeof (hbd_status_entry -> trigger_data ));
1172
+ hbd_status_entry -> size = (diag_buffer -> size / 1024 );
1173
+ hbd_status_entry ++ ;
1174
+ }
1175
+ hbd_status -> element_trigger_format =
1176
+ MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_DATA ;
1177
+
1178
+ if (data_in_sz < 4 ) {
1179
+ dprint_bsg_err (mrioc , "%s: invalid size passed\n" , __func__ );
1180
+ rval = - EINVAL ;
1181
+ goto out ;
1182
+ }
1183
+ min_length = min (data_in_sz , length );
1184
+ if (job -> request_payload .payload_len >= min_length ) {
1185
+ sg_copy_from_buffer (job -> request_payload .sg_list ,
1186
+ job -> request_payload .sg_cnt ,
1187
+ hbd_status , min_length );
1188
+ rval = 0 ;
1189
+ }
1190
+ out :
1191
+ kfree (hbd_status );
1192
+ return rval ;
1193
+ }
1194
+
1195
+
943
1196
/**
944
1197
* mpi3mr_enable_logdata - Handler for log data enable
945
1198
* @mrioc: Adapter instance reference
@@ -1368,6 +1621,18 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
1368
1621
case MPI3MR_DRVBSG_OPCODE_PELENABLE :
1369
1622
rval = mpi3mr_bsg_pel_enable (mrioc , job );
1370
1623
break ;
1624
+ case MPI3MR_DRVBSG_OPCODE_QUERY_HDB :
1625
+ rval = mpi3mr_bsg_query_hdb (mrioc , job );
1626
+ break ;
1627
+ case MPI3MR_DRVBSG_OPCODE_REPOST_HDB :
1628
+ rval = mpi3mr_bsg_repost_hdb (mrioc , job );
1629
+ break ;
1630
+ case MPI3MR_DRVBSG_OPCODE_UPLOAD_HDB :
1631
+ rval = mpi3mr_bsg_upload_hdb (mrioc , job );
1632
+ break ;
1633
+ case MPI3MR_DRVBSG_OPCODE_REFRESH_HDB_TRIGGERS :
1634
+ rval = mpi3mr_bsg_refresh_hdb_triggers (mrioc , job );
1635
+ break ;
1371
1636
case MPI3MR_DRVBSG_OPCODE_UNKNOWN :
1372
1637
default :
1373
1638
pr_err ("%s: unsupported driver command opcode %d\n" ,
0 commit comments