00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00034
00035
00036 #include <linux/module.h>
00037 #include <linux/jiffies.h>
00038 #include <linux/slab.h>
00039
00040 #include "soe_request.h"
00041
00042
00043
00046 #define EC_SOE_REQUEST_RESPONSE_TIMEOUT 1000
00047
00048
00049
00050 void ec_soe_request_clear_data(ec_soe_request_t *);
00051
00052
00053
00056 void ec_soe_request_init(
00057 ec_soe_request_t *req
00058 )
00059 {
00060 INIT_LIST_HEAD(&req->list);
00061 req->drive_no = 0x00;
00062 req->idn = 0x0000;
00063 req->al_state = EC_AL_STATE_INIT;
00064 req->data = NULL;
00065 req->mem_size = 0;
00066 req->data_size = 0;
00067 req->dir = EC_DIR_INVALID;
00068 req->state = EC_INT_REQUEST_INIT;
00069 req->jiffies_sent = 0U;
00070 req->error_code = 0x0000;
00071 }
00072
00073
00074
00077 void ec_soe_request_clear(
00078 ec_soe_request_t *req
00079 )
00080 {
00081 ec_soe_request_clear_data(req);
00082 }
00083
00084
00085
00090 int ec_soe_request_copy(
00091 ec_soe_request_t *req,
00092 const ec_soe_request_t *other
00093 )
00094 {
00095 req->drive_no = other->drive_no;
00096 req->idn = other->idn;
00097 req->al_state = other->al_state;
00098 return ec_soe_request_copy_data(req, other->data, other->data_size);
00099 }
00100
00101
00102
00105 void ec_soe_request_set_drive_no(
00106 ec_soe_request_t *req,
00107 uint8_t drive_no
00108 )
00109 {
00110 req->drive_no = drive_no;
00111 }
00112
00113
00114
00117 void ec_soe_request_set_idn(
00118 ec_soe_request_t *req,
00119 uint16_t idn
00120 )
00121 {
00122 req->idn = idn;
00123 }
00124
00125
00126
00129 void ec_soe_request_clear_data(
00130 ec_soe_request_t *req
00131 )
00132 {
00133 if (req->data) {
00134 kfree(req->data);
00135 req->data = NULL;
00136 }
00137
00138 req->mem_size = 0;
00139 req->data_size = 0;
00140 }
00141
00142
00143
00150 int ec_soe_request_alloc(
00151 ec_soe_request_t *req,
00152 size_t size
00153 )
00154 {
00155 if (size <= req->mem_size)
00156 return 0;
00157
00158 ec_soe_request_clear_data(req);
00159
00160 if (!(req->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
00161 EC_ERR("Failed to allocate %zu bytes of SoE memory.\n", size);
00162 return -ENOMEM;
00163 }
00164
00165 req->mem_size = size;
00166 req->data_size = 0;
00167 return 0;
00168 }
00169
00170
00171
00179 int ec_soe_request_copy_data(
00180 ec_soe_request_t *req,
00181 const uint8_t *source,
00182 size_t size
00183 )
00184 {
00185 int ret = ec_soe_request_alloc(req, size);
00186 if (ret < 0)
00187 return ret;
00188
00189 memcpy(req->data, source, size);
00190 req->data_size = size;
00191 return 0;
00192 }
00193
00194
00195
00203 int ec_soe_request_append_data(
00204 ec_soe_request_t *req,
00205 const uint8_t *source,
00206 size_t size
00207 )
00208 {
00209 if (req->data_size + size > req->mem_size) {
00210 size_t new_size = req->mem_size ? req->mem_size * 2 : size;
00211 uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL);
00212 if (!new_data) {
00213 EC_ERR("Failed to allocate %zu bytes of SoE memory.\n",
00214 new_size);
00215 return -ENOMEM;
00216 }
00217 memcpy(new_data, req->data, req->data_size);
00218 kfree(req->data);
00219 req->data = new_data;
00220 req->mem_size = new_size;
00221 }
00222
00223 memcpy(req->data + req->data_size, source, size);
00224 req->data_size += size;
00225 return 0;
00226 }
00227
00228
00229
00232 void ec_soe_request_read(
00233 ec_soe_request_t *req
00234 )
00235 {
00236 req->dir = EC_DIR_INPUT;
00237 req->state = EC_INT_REQUEST_QUEUED;
00238 req->error_code = 0x0000;
00239 }
00240
00241
00242
00245 void ec_soe_request_write(
00246 ec_soe_request_t *req
00247 )
00248 {
00249 req->dir = EC_DIR_OUTPUT;
00250 req->state = EC_INT_REQUEST_QUEUED;
00251 req->error_code = 0x0000;
00252 }
00253
00254