| /* | |
| * | |
| ************************************************************************** | |
| ** STMicroelectronics ** | |
| ************************************************************************** | |
| ** [email protected] ** | |
| ************************************************************************** | |
| * * | |
| * FTS functions for getting frames * | |
| * * | |
| ************************************************************************** | |
| ************************************************************************** | |
| * | |
| */ | |
| /*! | |
| * \file ftsFrame.c | |
| * \brief Contains all the functions to work with frames | |
| */ | |
| #include "ftsCompensation.h" | |
| #include "ftsCore.h" | |
| #include "ftsError.h" | |
| #include "ftsFrame.h" | |
| #include "ftsHardware.h" | |
| #include "ftsIO.h" | |
| #include "ftsSoftware.h" | |
| #include "ftsTool.h" | |
| #include "ftsTime.h" | |
| #include <linux/errno.h> | |
| #include <linux/kernel.h> | |
| #include <linux/module.h> | |
| #include <linux/slab.h> | |
| #include <linux/string.h> | |
| #include <stdarg.h> | |
| #include <linux/serio.h> | |
| #include <linux/time.h> | |
| #include <linux/delay.h> | |
| #include <linux/ctype.h> | |
| extern SysInfo systemInfo; /* /< forward declaration of the global variable | |
| * of containing System Info Data */ | |
| /** | |
| * Read the channels lengths from the config memory | |
| * @return OK if success or an error code which specify the type of error | |
| */ | |
| int getChannelsLength(void) | |
| { | |
| int ret; | |
| u8 data[2]; | |
| if (data == NULL) { | |
| pr_err("getChannelsLength: ERROR %08X\n", ERROR_ALLOC); | |
| return ERROR_ALLOC; | |
| } | |
| ret = readConfig(ADDR_CONFIG_SENSE_LEN, data, 2); | |
| if (ret < OK) { | |
| pr_err("getChannelsLength: ERROR %08X\n", ret); | |
| return ret; | |
| } | |
| systemInfo.u8_scrRxLen = (int)data[0]; | |
| systemInfo.u8_scrTxLen = (int)data[1]; | |
| pr_info("Force_len = %d Sense_Len = %d\n", | |
| systemInfo.u8_scrTxLen, systemInfo.u8_scrRxLen); | |
| return OK; | |
| } | |
| /** | |
| * Read and pack the frame data related to the nodes | |
| * @param address address in memory when the frame data node start | |
| * @param size amount of data to read | |
| * @param frame pointer to an array of bytes which will contain the frame node | |
| * data | |
| * @return OK if success or an error code which specify the type of error | |
| */ | |
| int getFrameData(u16 address, int size, short *frame) | |
| { | |
| int i, j, ret; | |
| u8 *data = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); | |
| if (data == NULL) { | |
| pr_err("getFrameData: ERROR %08X\n", ERROR_ALLOC); | |
| return ERROR_ALLOC; | |
| } | |
| ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, | |
| size, DUMMY_FRAMEBUFFER); | |
| if (ret < OK) { | |
| pr_err("getFrameData: ERROR %08X\n", ERROR_BUS_R); | |
| kfree(data); | |
| return ERROR_BUS_R; | |
| } | |
| j = 0; | |
| for (i = 0; i < size; i += 2) { | |
| frame[j] = (short)((data[i + 1] << 8) + data[i]); | |
| j++; | |
| } | |
| kfree(data); | |
| return OK; | |
| } | |
| /** | |
| * Return the number of Sense Channels (Rx) | |
| * @return number of Rx channels | |
| */ | |
| int getSenseLen(void) | |
| { | |
| if (systemInfo.u8_scrRxLen == 0) | |
| getChannelsLength(); | |
| return systemInfo.u8_scrRxLen; | |
| } | |
| /** | |
| * Return the number of Force Channels (Tx) | |
| * @return number of Tx channels | |
| */ | |
| int getForceLen(void) | |
| { | |
| if (systemInfo.u8_scrTxLen == 0) | |
| getChannelsLength(); | |
| return systemInfo.u8_scrTxLen; | |
| } | |
| /******************** New API **************************/ | |
| /** | |
| * Read a MS Frame from frame buffer memory | |
| * @param type type of MS frame to read | |
| * @param frame pointer to MutualSenseFrame variable which will contain the | |
| * data | |
| * @return > 0 if success specifying the number of node into the frame or | |
| * an error code which specify the type of error | |
| */ | |
| int getMSFrame3(MSFrameType type, MutualSenseFrame *frame) | |
| { | |
| u16 offset; | |
| int ret, force_len, sense_len; | |
| force_len = getForceLen(); | |
| sense_len = getSenseLen(); | |
| frame->node_data = NULL; | |
| pr_debug("%s: Starting to get frame %02X\n", __func__, | |
| type); | |
| switch (type) { | |
| case MS_RAW: | |
| offset = systemInfo.u16_msTchRawAddr; | |
| goto LOAD_NORM; | |
| case MS_FILTER: | |
| offset = systemInfo.u16_msTchFilterAddr; | |
| goto LOAD_NORM; | |
| case MS_STRENGTH: | |
| offset = systemInfo.u16_msTchStrenAddr; | |
| goto LOAD_NORM; | |
| case MS_BASELINE: | |
| offset = systemInfo.u16_msTchBaselineAddr; | |
| LOAD_NORM: | |
| if (force_len == 0 || sense_len == 0) { | |
| pr_err("%s: number of channels not initialized ERROR %08X\n", | |
| __func__, ERROR_CH_LEN); | |
| return ERROR_CH_LEN | ERROR_GET_FRAME; | |
| } | |
| break; | |
| case MS_KEY_RAW: | |
| offset = systemInfo.u16_keyRawAddr; | |
| goto LOAD_KEY; | |
| case MS_KEY_FILTER: | |
| offset = systemInfo.u16_keyFilterAddr; | |
| goto LOAD_KEY; | |
| case MS_KEY_STRENGTH: | |
| offset = systemInfo.u16_keyStrenAddr; | |
| goto LOAD_KEY; | |
| case MS_KEY_BASELINE: | |
| offset = systemInfo.u16_keyBaselineAddr; | |
| LOAD_KEY: | |
| if (systemInfo.u8_keyLen == 0) { | |
| pr_err("%s: number of channels not initialized ERROR %08X\n", | |
| __func__, ERROR_CH_LEN); | |
| return ERROR_CH_LEN | ERROR_GET_FRAME; | |
| } | |
| force_len = 1; | |
| sense_len = systemInfo.u8_keyLen; | |
| break; | |
| case FRC_RAW: | |
| offset = systemInfo.u16_frcRawAddr; | |
| goto LOAD_FRC; | |
| case FRC_FILTER: | |
| offset = systemInfo.u16_frcFilterAddr; | |
| goto LOAD_FRC; | |
| case FRC_STRENGTH: | |
| offset = systemInfo.u16_frcStrenAddr; | |
| goto LOAD_FRC; | |
| case FRC_BASELINE: | |
| offset = systemInfo.u16_frcBaselineAddr; | |
| LOAD_FRC: | |
| if (force_len == 0) { | |
| pr_err("%s: number of channels not initialized ERROR %08X\n", | |
| __func__, ERROR_CH_LEN); | |
| return ERROR_CH_LEN | ERROR_GET_FRAME; | |
| } | |
| sense_len = 1; | |
| break; | |
| default: | |
| pr_err("%s: Invalid type ERROR %08X\n", __func__, | |
| ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME); | |
| return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; | |
| } | |
| frame->node_data_size = ((force_len) * sense_len); | |
| frame->header.force_node = force_len; | |
| frame->header.sense_node = sense_len; | |
| frame->header.type = type; | |
| pr_debug("%s: Force_len = %d Sense_len = %d Offset = %04X\n", | |
| __func__, force_len, sense_len, offset); | |
| frame->node_data = (short *)kmalloc(frame->node_data_size * | |
| sizeof(short), GFP_KERNEL); | |
| if (frame->node_data == NULL) { | |
| pr_err("%s: ERROR %08X\n", __func__, | |
| ERROR_ALLOC | ERROR_GET_FRAME); | |
| return ERROR_ALLOC | ERROR_GET_FRAME; | |
| } | |
| ret = getFrameData(offset, frame->node_data_size * BYTES_PER_NODE, | |
| (frame->node_data)); | |
| if (ret < OK) { | |
| pr_err("%s: ERROR %08X\n", __func__, ERROR_GET_FRAME_DATA); | |
| kfree(frame->node_data); | |
| frame->node_data = NULL; | |
| return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| } | |
| /* if you want to access one node i,j, | |
| * compute the offset like: offset = i*columns + j = > frame[i, j] */ | |
| pr_debug("Frame acquired!\n"); | |
| return frame->node_data_size; | |
| /* return the number of data put inside frame */ | |
| } | |
| /** | |
| * Read a SS Frame from frame buffer | |
| * @param type type of SS frame to read | |
| * @param frame pointer to SelfSenseFrame variable which will contain the data | |
| * @return > 0 if success specifying the number of node into frame or an | |
| * error code which specify the type of error | |
| */ | |
| int getSSFrame3(SSFrameType type, SelfSenseFrame *frame) | |
| { | |
| u16 offset_force, offset_sense; | |
| int ret; | |
| frame->force_data = NULL; | |
| frame->sense_data = NULL; | |
| frame->header.force_node = getForceLen(); /* use getForce/SenseLen | |
| * because introduce | |
| * a recover mechanism | |
| * in case of len =0 */ | |
| frame->header.sense_node = getSenseLen(); | |
| if (frame->header.force_node == 0 || frame->header.sense_node == 0) { | |
| pr_err("%s: number of channels not initialized ERROR %08X\n", | |
| __func__, ERROR_CH_LEN); | |
| return ERROR_CH_LEN | ERROR_GET_FRAME; | |
| } | |
| pr_info("%s: Starting to get frame %02X\n", __func__, type); | |
| switch (type) { | |
| case SS_RAW: | |
| offset_force = systemInfo.u16_ssTchTxRawAddr; | |
| offset_sense = systemInfo.u16_ssTchRxRawAddr; | |
| break; | |
| case SS_FILTER: | |
| offset_force = systemInfo.u16_ssTchTxFilterAddr; | |
| offset_sense = systemInfo.u16_ssTchRxFilterAddr; | |
| break; | |
| case SS_STRENGTH: | |
| offset_force = systemInfo.u16_ssTchTxStrenAddr; | |
| offset_sense = systemInfo.u16_ssTchRxStrenAddr; | |
| break; | |
| case SS_BASELINE: | |
| offset_force = systemInfo.u16_ssTchTxBaselineAddr; | |
| offset_sense = systemInfo.u16_ssTchRxBaselineAddr; | |
| break; | |
| case SS_HVR_RAW: | |
| offset_force = systemInfo.u16_ssHvrTxRawAddr; | |
| offset_sense = systemInfo.u16_ssHvrRxRawAddr; | |
| break; | |
| case SS_HVR_FILTER: | |
| offset_force = systemInfo.u16_ssHvrTxFilterAddr; | |
| offset_sense = systemInfo.u16_ssHvrRxFilterAddr; | |
| break; | |
| case SS_HVR_STRENGTH: | |
| offset_force = systemInfo.u16_ssHvrTxStrenAddr; | |
| offset_sense = systemInfo.u16_ssHvrRxStrenAddr; | |
| break; | |
| case SS_HVR_BASELINE: | |
| offset_force = systemInfo.u16_ssHvrTxBaselineAddr; | |
| offset_sense = systemInfo.u16_ssHvrRxBaselineAddr; | |
| break; | |
| case SS_PRX_RAW: | |
| offset_force = systemInfo.u16_ssPrxTxRawAddr; | |
| offset_sense = systemInfo.u16_ssPrxRxRawAddr; | |
| break; | |
| case SS_PRX_FILTER: | |
| offset_force = systemInfo.u16_ssPrxTxFilterAddr; | |
| offset_sense = systemInfo.u16_ssPrxRxFilterAddr; | |
| break; | |
| case SS_PRX_STRENGTH: | |
| offset_force = systemInfo.u16_ssPrxTxStrenAddr; | |
| offset_sense = systemInfo.u16_ssPrxRxStrenAddr; | |
| break; | |
| case SS_PRX_BASELINE: | |
| offset_force = systemInfo.u16_ssPrxTxBaselineAddr; | |
| offset_sense = systemInfo.u16_ssPrxRxBaselineAddr; | |
| break; | |
| case SS_DETECT_RAW: | |
| if (systemInfo.u8_ssDetScanSet == 0) { | |
| offset_force = systemInfo.u16_ssDetRawAddr; | |
| offset_sense = 0; | |
| frame->header.sense_node = 0; | |
| } else { | |
| offset_sense = systemInfo.u16_ssDetRawAddr; | |
| offset_force = 0; | |
| frame->header.force_node = 0; | |
| } | |
| break; | |
| case SS_DETECT_FILTER: | |
| if (systemInfo.u8_ssDetScanSet == 0) { | |
| offset_force = systemInfo.u16_ssDetFilterAddr; | |
| offset_sense = 0; | |
| frame->header.sense_node = 0; | |
| } else { | |
| offset_sense = systemInfo.u16_ssDetFilterAddr; | |
| offset_force = 0; | |
| frame->header.force_node = 0; | |
| } | |
| break; | |
| case SS_DETECT_BASELINE: | |
| if (systemInfo.u8_ssDetScanSet == 0) { | |
| offset_force = systemInfo.u16_ssDetBaselineAddr; | |
| offset_sense = 0; | |
| frame->header.sense_node = 0; | |
| } else { | |
| offset_sense = systemInfo.u16_ssDetBaselineAddr; | |
| offset_force = 0; | |
| frame->header.force_node = 0; | |
| } | |
| break; | |
| case SS_DETECT_STRENGTH: | |
| if (systemInfo.u8_ssDetScanSet == 0) { | |
| offset_force = systemInfo.u16_ssDetStrenAddr; | |
| offset_sense = 0; | |
| frame->header.sense_node = 0; | |
| } else { | |
| offset_sense = systemInfo.u16_ssDetStrenAddr; | |
| offset_force = 0; | |
| frame->header.force_node = 0; | |
| } | |
| break; | |
| default: | |
| pr_err("%s: Invalid type ERROR %08X\n", __func__, | |
| ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME); | |
| return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; | |
| } | |
| frame->header.type = type; | |
| pr_info("%s: Force_len = %d Sense_len = %d Offset_force = %04X Offset_sense = %04X\n", | |
| __func__, frame->header.force_node, | |
| frame->header.sense_node, | |
| offset_force, offset_sense); | |
| frame->force_data = (short *)kmalloc(frame->header.force_node * | |
| sizeof(short), GFP_KERNEL); | |
| if (frame->force_data == NULL) { | |
| pr_err("%s: can not allocate force_data ERROR %08X\n", | |
| __func__, ERROR_ALLOC | ERROR_GET_FRAME); | |
| return ERROR_ALLOC | ERROR_GET_FRAME; | |
| } | |
| frame->sense_data = (short *)kmalloc(frame->header.sense_node * | |
| sizeof(short), GFP_KERNEL); | |
| if (frame->sense_data == NULL) { | |
| kfree(frame->force_data); | |
| frame->force_data = NULL; | |
| pr_err("%s: can not allocate sense_data ERROR %08X\n", | |
| __func__, ERROR_ALLOC | ERROR_GET_FRAME); | |
| return ERROR_ALLOC | ERROR_GET_FRAME; | |
| } | |
| ret = getFrameData(offset_force, frame->header.force_node * | |
| BYTES_PER_NODE, (frame->force_data)); | |
| if (ret < OK) { | |
| pr_err("%s: error while reading force data ERROR %08X\n", | |
| __func__, ERROR_GET_FRAME_DATA); | |
| kfree(frame->force_data); | |
| frame->force_data = NULL; | |
| kfree(frame->sense_data); | |
| frame->sense_data = NULL; | |
| return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| } | |
| ret = getFrameData(offset_sense, frame->header.sense_node * | |
| BYTES_PER_NODE, (frame->sense_data)); | |
| if (ret < OK) { | |
| pr_err("%s: error while reading sense data ERROR %08X\n", | |
| __func__, ERROR_GET_FRAME_DATA); | |
| kfree(frame->force_data); | |
| frame->force_data = NULL; | |
| kfree(frame->sense_data); | |
| frame->sense_data = NULL; | |
| return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| } | |
| /* if you want to access one node i,j, | |
| * the offset like: offset = i*columns + j = > frame[i, j] */ | |
| pr_info("Frame acquired!\n"); | |
| return frame->header.force_node + frame->header.sense_node; | |
| /* return the number of data put inside frame */ | |
| } | |
| /** | |
| * Read Initialization Data Header and check that the type loaded match with | |
| * the one previously requested | |
| * @param type type of Initialization data requested @link load_opt Load Host | |
| * Data Option @endlink | |
| * @param msHeader pointer to DataHeader variable which will contain the header | |
| * info for the MS frame | |
| * @param ssHeader pointer to DataHeader variable which will contain the header | |
| * info for the SS frame | |
| * @param address pointer to a variable which will contain the updated address | |
| * to the next data | |
| * @return OK if success or an error code which specify the type of error | |
| */ | |
| int readSyncDataHeader(u8 type, DataHeader *msHeader, DataHeader *ssHeader, | |
| u64 *address) | |
| { | |
| u64 offset = ADDR_FRAMEBUFFER; | |
| u8 data[SYNCFRAME_DATA_HEADER]; | |
| int ret; | |
| ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data, | |
| SYNCFRAME_DATA_HEADER, DUMMY_FRAMEBUFFER); | |
| if (ret < OK) { /* i2c function have already a retry mechanism */ | |
| pr_err("%s: error while reading data header ERROR %08X\n", | |
| __func__, ret); | |
| return ret; | |
| } | |
| pr_info("Read Data Header done!\n"); | |
| if (data[0] != HEADER_SIGNATURE) { | |
| pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n", | |
| __func__, data[0], HEADER_SIGNATURE, | |
| ERROR_WRONG_DATA_SIGN); | |
| return ERROR_WRONG_DATA_SIGN; | |
| } | |
| if (data[1] != type) { | |
| pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n", | |
| __func__, data[1], type, ERROR_DIFF_DATA_TYPE); | |
| return ERROR_DIFF_DATA_TYPE; | |
| } | |
| pr_info("Type = %02X of SyncFrame data OK!\n", type); | |
| msHeader->force_node = data[5]; | |
| msHeader->sense_node = data[6]; | |
| pr_info("MS Frame force_node = %d, sense_node = %d\n", | |
| msHeader->force_node, msHeader->sense_node); | |
| ssHeader->force_node = data[7]; | |
| ssHeader->sense_node = data[8]; | |
| pr_info("SS Frame force_node = %d, sense_node = %d\n", | |
| ssHeader->force_node, ssHeader->sense_node); | |
| *address = offset + SYNCFRAME_DATA_HEADER + data[4]; | |
| return OK; | |
| } | |
| /** | |
| * Read a Sync Frame from frame buffer which contain MS and SS data collected | |
| * for the same scan | |
| * @param type type of Sync frame to read, possible values: | |
| * LOAD_SYNC_FRAME_RAW, LOAD_SYNC_FRAME_FILTER, LOAD_SYNC_FRAME_BASELINE, | |
| * LOAD_SYNC_FRAME_STRENGTH | |
| * @param msFrame pointer to MutualSenseFrame variable which will contain the | |
| * MS data | |
| * @param ssFrame pointer to SelfSenseFrame variable which will contain the SS | |
| * data | |
| * @return >0 if success specifying the total number of nodes copied into | |
| * msFrame and ssFrame or an error code which specify the type of error | |
| */ | |
| int getSyncFrame(u8 type, MutualSenseFrame *msFrame, SelfSenseFrame *ssFrame) | |
| { | |
| int res; | |
| u64 address; | |
| msFrame->node_data = NULL; | |
| ssFrame->force_data = NULL; | |
| ssFrame->sense_data = NULL; | |
| pr_info("%s: Starting to get Sync Frame %02X...\n", __func__, type); | |
| switch (type) { | |
| case LOAD_SYNC_FRAME_RAW: | |
| msFrame->header.type = MS_RAW; | |
| ssFrame->header.type = SS_RAW; | |
| break; | |
| case LOAD_SYNC_FRAME_FILTER: | |
| msFrame->header.type = MS_FILTER; | |
| ssFrame->header.type = SS_FILTER; | |
| break; | |
| case LOAD_SYNC_FRAME_BASELINE: | |
| msFrame->header.type = MS_BASELINE; | |
| ssFrame->header.type = SS_BASELINE; | |
| break; | |
| case LOAD_SYNC_FRAME_STRENGTH: | |
| msFrame->header.type = MS_STRENGTH; | |
| ssFrame->header.type = SS_STRENGTH; | |
| break; | |
| default: | |
| return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; | |
| } | |
| pr_info("%s: Requesting Sync Frame %02X...\n", __func__, type); | |
| res = requestSyncFrame(type); | |
| if (res < OK) { | |
| pr_err("%s: error while requesting Sync Frame ERROR %08X\n", | |
| __func__, res | ERROR_GET_FRAME_DATA); | |
| return res | ERROR_GET_FRAME_DATA; | |
| } | |
| res = readSyncDataHeader(type, &(msFrame->header), &(ssFrame->header), | |
| &address); | |
| if (res < OK) { | |
| pr_err("%s: error while reading Sync Frame header... ERROR %08X\n", | |
| __func__, res | ERROR_GET_FRAME_DATA); | |
| return res | ERROR_GET_FRAME_DATA; | |
| } | |
| msFrame->node_data_size = msFrame->header.force_node * | |
| msFrame->header.sense_node; | |
| msFrame->node_data = (short *)kmalloc(msFrame->node_data_size * | |
| sizeof(short), GFP_KERNEL); | |
| if (msFrame->node_data == NULL) { | |
| pr_err("%s: impossible allocate memory for MS frame... ERROR %08X\n", | |
| __func__, ERROR_ALLOC | ERROR_GET_FRAME); | |
| return ERROR_ALLOC | ERROR_GET_FRAME; | |
| } | |
| pr_info("%s: Getting MS frame at %llx...\n", __func__, address); | |
| res = getFrameData(address, (msFrame->node_data_size) * BYTES_PER_NODE, | |
| (msFrame->node_data)); | |
| if (res < OK) { | |
| pr_err("%s: error while getting MS data...ERROR %08X\n", | |
| __func__, res); | |
| res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| goto ERROR; | |
| } | |
| /* move the offset */ | |
| address += (msFrame->node_data_size) * BYTES_PER_NODE; | |
| ssFrame->force_data = (short *)kmalloc(ssFrame->header.force_node * | |
| sizeof(short), GFP_KERNEL); | |
| if (ssFrame->force_data == NULL) { | |
| pr_err("%s: impossible allocate memory for SS force frame...ERROR %08X\n", | |
| __func__, ERROR_ALLOC | ERROR_GET_FRAME); | |
| res = ERROR_ALLOC | ERROR_GET_FRAME; | |
| goto ERROR; | |
| } | |
| pr_info("%s: Getting SS force frame at %llx...\n", __func__, address); | |
| res = getFrameData(address, (ssFrame->header.force_node) * | |
| BYTES_PER_NODE, (ssFrame->force_data)); | |
| if (res < OK) { | |
| pr_err("%s: error while getting SS force data...ERROR %08X\n", | |
| __func__, res); | |
| res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| goto ERROR; | |
| } | |
| /* move the offset */ | |
| address += (ssFrame->header.force_node) * BYTES_PER_NODE; | |
| ssFrame->sense_data = (short *)kmalloc(ssFrame->header.sense_node * | |
| sizeof(short), GFP_KERNEL); | |
| if (ssFrame->sense_data == NULL) { | |
| pr_err("%s: impossible allocate memory for SS sense frame...ERROR %08X\n", | |
| __func__, ERROR_ALLOC | ERROR_GET_FRAME); | |
| res = ERROR_ALLOC | ERROR_GET_FRAME; | |
| goto ERROR; | |
| } | |
| pr_info("%s: Getting SS sense frame at %llx...\n", __func__, address); | |
| res = getFrameData(address, (ssFrame->header.sense_node) * | |
| BYTES_PER_NODE, (ssFrame->sense_data)); | |
| if (res < OK) { | |
| pr_err("%s: error while getting SS sense data...ERROR %08X\n", | |
| __func__, res); | |
| res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; | |
| goto ERROR; | |
| } | |
| ERROR: | |
| if (res < OK) { | |
| if (msFrame->node_data != NULL) { | |
| kfree(msFrame->node_data); | |
| msFrame->node_data = NULL; | |
| } | |
| if (ssFrame->force_data != NULL) { | |
| kfree(ssFrame->force_data); | |
| ssFrame->force_data = NULL; | |
| } | |
| if (ssFrame->sense_data != NULL) { | |
| kfree(ssFrame->sense_data); | |
| ssFrame->sense_data = NULL; | |
| } | |
| pr_err("Getting Sync Frame FAILED! ERROR %08X!\n", res); | |
| } else { | |
| pr_info("Getting Sync Frame FINISHED!\n"); | |
| res = msFrame->node_data_size + ssFrame->header.force_node + | |
| ssFrame->header.sense_node; | |
| } | |
| return res; | |
| } |