Skip to contentSkip to conversation

DVB:Siano drivers - Improve firmware load and reload mechanism.

PATCH NAK Doron Cohen 2 participants 2 messages Sep 20, 2011 – Sep 23, 2011 Media (V4L/DVB)

lore
Share & tools
lore
#0 lore raw

PATCH 12/17 DVB:Siano drivers - Improve firmware load and reload mechanism.

Hi,
This patch step Improve firmware load and reload mechanism in order to support new siano devices and match all existing devices.

Thanks,
Doron Cohen

-----------------------

Quoted 1 line

From 59062b9fbc2f3c28cbb1ec014c6ed5a3e065a7de Mon Sep 17 00:00:00 2001

From: Doron Cohen <[email protected]>
Date: Tue, 20 Sep 2011 08:22:29 +0300
Subject: [PATCH 16/21] Improve firmware load and reload mechanism in order to support new siano devices and match all existing devices.

---
 drivers/media/dvb/siano/smscoreapi.c |  530
+++++++++++++++++++++++++++-------
 1 files changed, 423 insertions(+), 107 deletions(-)
(quoted diff) +0 -0

b/drivers/media/dvb/siano/smscoreapi.c
index db24391..e50e356 100644

drivers/media/dvb/siano/smscoreapi.c +0 -0
@@ -312,6 +312,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer,

void *common_buffer,
cb->p = buffer;
cb->offset_in_common = buffer - (u8 *) common_buffer; cb->phys = common_buffer_phys + cb->offset_in_common;
+ cb->offset=0;

return cb;
}
@@ -352,6 +353,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
/* init completion events */ init_completion(&dev->version_ex_done); init_completion(&dev->data_download_done);
+ init_completion(&dev->data_validity_done);
init_completion(&dev->trigger_done); init_completion(&dev->init_device_done); init_completion(&dev->reload_start_done);
@@ -360,6 +362,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
init_completion(&dev->gpio_set_level_done); init_completion(&dev->gpio_get_level_done); init_completion(&dev->ir_init_done);
+ init_completion(&dev->device_ready_done);

/* Buffer management */ init_waitqueue_head(&dev->buffer_mng_waitq);
@@ -426,7 +429,13 @@ EXPORT_SYMBOL_GPL(smscore_register_device);

static int smscore_sendrequest_and_wait(struct smscore_device_t
*coredev,
void *buffer, size_t size, struct completion *completion) {
- int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+ int rc;
+
+ if (completion == NULL)
+ return -EINVAL;
+ init_completion(completion);
+
+ rc = coredev->sendrequest_handler(coredev->context, buffer, size);
if (rc < 0) {
sms_info("sendrequest returned error %d", rc); return rc;
@@ -535,7 +544,8 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
{
struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; struct SmsMsgHdr_S *msg;
- u32 mem_address;
+ u32 mem_address, calc_checksum = 0;
+ u32 i, *ptr;
u8 *payload = firmware->Payload;
int rc = 0;
firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
@@ -563,9 +573,17 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
rc = smscore_sendrequest_and_wait(coredev, msg,
msg->msgLength, &coredev->reload_start_done);
+
+ if (rc < 0) {
+ sms_err("device reload failed, rc %d", rc);
+ goto exit_fw_download;
+ }
+
mem_address = *(u32 *) &payload[20];
}

+ for (i = 0, ptr = (u32*)firmware->Payload; i < firmware->Length/4 ; i
++, ptr++)
+ calc_checksum += *ptr;
while (size && rc >= 0) {
struct SmsDataDownload_S *DataMsg =
(struct SmsDataDownload_S *) msg;
@@ -578,14 +596,9 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
DataMsg->MemAddr = mem_address; memcpy(DataMsg->Payload, payload, payload_size);

- if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
- (coredev->mode == SMSHOSTLIB_DEVMD_NONE))
- rc = coredev->sendrequest_handler(
- coredev->context, DataMsg,
- DataMsg->xMsgHeader.msgLength);
- else
- rc = smscore_sendrequest_and_wait(
- coredev, DataMsg,
+
+
+ rc = smscore_sendrequest_and_wait(coredev, DataMsg,
DataMsg->xMsgHeader.msgLength, &coredev->data_download_done);

@@ -594,44 +607,63 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
mem_address += payload_size;
}

- if (rc >= 0) {
+ if (rc < 0)
+ goto exit_fw_download;
+
+ sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
calc_checksum);
+ SMS_INIT_MSG(msg, MSG_SMS_DATA_VALIDITY_REQ,
+ sizeof(struct SmsMsgHdr_S) +
+ sizeof(u32) * 3);
+ ((struct SmsMsgData_S *)msg)->msgData[0] = firmware->StartAddress;
+ /* Entry point */
+ ((struct SmsMsgData_S *)msg)->msgData[1] = firmware->Length;
+ ((struct SmsMsgData_S *)msg)->msgData[2] = 0; /* Regular checksum*/
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = smscore_sendrequest_and_wait(coredev, msg, ((struct SmsMsgData_S
*)msg)->xMsgHeader.msgLength, &coredev->data_validity_done);
+ if (rc < 0)
+ goto exit_fw_download;
+
+
if (coredev->mode == SMSHOSTLIB_DEVMD_NONE) {
struct SmsMsgData_S *TriggerMsg =
(struct SmsMsgData_S *) msg;

+ sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
sizeof(struct SmsMsgHdr_S) + sizeof(u32) * 5);

TriggerMsg->msgData[0] = firmware->StartAddress;
/* Entry point */
- TriggerMsg->msgData[1] = 5; /* Priority */
+ TriggerMsg->msgData[1] = 6; /* Priority */
TriggerMsg->msgData[2] = 0x200; /* Stack size */ TriggerMsg->msgData[3] = 0; /* Parameter */ TriggerMsg->msgData[4] = 4; /* Task ID */

- if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
- rc = coredev->sendrequest_handler(
- coredev->context, TriggerMsg,
- TriggerMsg->xMsgHeader.msgLength);
- msleep(100);
- } else
- rc = smscore_sendrequest_and_wait(
- coredev, TriggerMsg,
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = smscore_sendrequest_and_wait(coredev,
+ TriggerMsg,
TriggerMsg->xMsgHeader.msgLength, &coredev->trigger_done);
} else {
SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
sizeof(struct SmsMsgHdr_S));
-
- rc = coredev->sendrequest_handler(coredev->context,
- msg, msg->msgLength);
- }
- msleep(500);
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = coredev->sendrequest_handler(coredev->context, msg,
+ msg->msgLength);
}

- sms_debug("rc=%d, postload=%p ", rc,
- coredev->postload_handler);
+ if (rc < 0)
+ goto exit_fw_download;
+
+ /*
+ * backward compatibility - wait to device_ready_done for
+ * not more than 400 ms
+ */
+ msleep(400);
+
+exit_fw_download:
+ sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler);

kfree(msg);

@@ -653,42 +685,211 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
* @return 0 on success, <0 on error.
*/
static int smscore_load_firmware_from_file(struct smscore_device_t
*coredev,
- char *filename,
- loadfirmware_t loadfirmware_handler)
-{
+ int mode, int lookup, loadfirmware_t loadfirmware_handler) {
int rc = -ENOENT;
+ u8 *fw_buf;
+ u32 fw_buf_size;
+
+#ifdef REQUEST_FIRMWARE_SUPPORTED
const struct firmware *fw;
- u8 *fw_buffer;

- if (loadfirmware_handler == NULL && !(coredev->device_flags &
- SMS_DEVICE_FAMILY2))
+ char* fw_filename = smscore_get_fw_filename(coredev, mode, lookup);
+ if (!strcmp(fw_filename,"none"))
+ return -ENOENT;
+
+ if (loadfirmware_handler == NULL && !(coredev->device_flags
+ & SMS_DEVICE_FAMILY2))
return -EINVAL;

- rc = request_firmware(&fw, filename, coredev->device);
+ rc = request_firmware(&fw, fw_filename, coredev->device);
if (rc < 0) {
- sms_info("failed to open \"%s\"", filename);
+ sms_info("failed to open \"%s\"", fw_filename);
return rc;
}
- sms_info("read FW %s, size=%zd", filename, fw->size);
- fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+ sms_info("read fw %s, buffer size=0x%x", fw_filename, fw->size);
+ fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
GFP_KERNEL | GFP_DMA);
- if (fw_buffer) {
- memcpy(fw_buffer, fw->data, fw->size);
+ if (!fw_buf) {
+ sms_info("failed to allocate firmware buffer");
+ return -ENOMEM;
+ }
+ memcpy(fw_buf, fw->data, fw->size);
+ fw_buf_size = fw->size;
+#else
+ if (!coredev->fw_buf) {
+ sms_info("missing fw file buffer");
+ return -EINVAL;
+ }
+ fw_buf = coredev->fw_buf;
+ fw_buf_size = coredev->fw_buf_size;
+#endif

rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
- smscore_load_firmware_family2(coredev,
- fw_buffer,
- fw->size) :
- loadfirmware_handler(coredev->context,
- fw_buffer, fw->size);
+ smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
+ : loadfirmware_handler(coredev->context, fw_buf,
+ fw_buf_size);
+
+ kfree(fw_buf);
+
+#ifdef REQUEST_FIRMWARE_SUPPORTED
+ release_firmware(fw);
+#else
+ coredev->fw_buf = NULL;
+ coredev->fw_buf_size = 0;
+#endif
+ return rc;
+}
+
+/**
+ * Send chunk of firmware data using SMS MSGs
+ * The motivation is to eliminate the need of big memory allocation in kernel for firmware
+ * download.
+ *
+ * @param coredev pointer to a coredev object returned by

+ *                smscore_register_device
+ * @param buffer  pointer to a buffer
+ * @param size    size of buffer

+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_send_fw_chunk(struct smscore_device_t *coredev,
+ void *buffer, size_t size)
+{
+
+ struct SmsMsgHdr_S *msg;
+ int rc = 0;
+ int offset = 0;
+
+ if (buffer == NULL)
+ {
+ sms_debug("Error: NULL buffer");
+ return -1;
+ }
+
+ /* First chunk */
+ if (coredev->start_address == 0)
+ {
+ struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+ coredev->start_address = le32_to_cpu(firmware->StartAddress);
+ coredev->current_address = coredev->start_address;
+ offset = 12;
+ size -= 12;
+
+ if (coredev->preload_handler)
+ {
+ rc = coredev->preload_handler(coredev->context);
+ if (rc < 0)
+ return rc;
+ }
+ }
+
+ /* PAGE_SIZE buffer shall be enough and dma aligned */
+ msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!msg)
+ return -ENOMEM;
+
+ while (size && rc >= 0) {
+ int payload_size;
+ struct SmsDataDownload_S *DataMsg;
+ sms_debug("sending MSG_SMS_DATA_DOWNLOAD_REQ");
+ DataMsg = (struct SmsDataDownload_S *) msg;
+ payload_size = min((int)size, SMS_MAX_PAYLOAD_SIZE);

- kfree(fw_buffer);
+ SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+ (u16) (sizeof(struct SmsMsgHdr_S) +
+ sizeof(u32) + payload_size));
+
+ DataMsg->MemAddr = coredev->current_address;
+ copy_from_user(DataMsg->Payload, (u8*)(buffer + offset),
payload_size);
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = smscore_sendrequest_and_wait(coredev, DataMsg,
+ DataMsg->xMsgHeader.msgLength,
+ &coredev->data_download_done);
+
+ size -= payload_size;
+ offset += payload_size;
+ coredev->current_address += payload_size;
+ }
+
+ kfree(msg);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(smscore_send_fw_chunk);
+
+
+/**
+ * Send last chunk of firmware data using SMS MSGs
+ *
+ * @param coredev pointer to a coredev object returned by

+ *                smscore_register_device
+ * @param buffer  pointer to a buffer
+ * @param size    size of buffer

+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_send_last_fw_chunk(struct smscore_device_t *coredev,
+ void *buffer, size_t size)
+{
+ int rc = 0;
+ struct SmsMsgHdr_S *msg;
+
+ rc = smscore_send_fw_chunk(coredev, buffer, size);
+ if (rc < 0)
+ return rc;
+
+ /* PAGE_SIZE buffer shall be enough and dma aligned */
+ msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!msg)
+ return -ENOMEM;
+
+ if (coredev->mode == SMSHOSTLIB_DEVMD_NONE) {
+ struct SmsMsgData_S *TriggerMsg =
+ (struct SmsMsgData_S *) msg;
+
+ sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+ SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+ sizeof(struct SmsMsgHdr_S) +
+ sizeof(u32) * 5);
+
+ TriggerMsg->msgData[0] = coredev->start_address;
+ /* Entry point */
+ TriggerMsg->msgData[1] = 6; /* Priority */
+ TriggerMsg->msgData[2] = 0x200; /* Stack size */
+ TriggerMsg->msgData[3] = 0; /* Parameter */
+ TriggerMsg->msgData[4] = 4; /* Task ID */
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = smscore_sendrequest_and_wait(coredev,
+ TriggerMsg,
+ TriggerMsg->xMsgHeader.msgLength,
+ &coredev->trigger_done);
} else {
- sms_info("failed to allocate firmware buffer");
- rc = -ENOMEM;
+ SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+ sizeof(struct SmsMsgHdr_S));
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = coredev->sendrequest_handler(coredev->context, msg,
+ msg->msgLength);
}

- release_firmware(fw);
+ /* clear start_address */
+ coredev->start_address = 0;
+
+ if (rc < 0)
+ goto exit_fw_download;
+
+ /*
+ * backward compatibility - wait to device_ready_done for
+ * not more than 400 ms
+ */
+ wait_for_completion_timeout(&coredev->device_ready_done,
+ msecs_to_jiffies(400));
+
+exit_fw_download:
+ sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler);
+
+ kfree(msg);

return rc;
}
@@ -712,6 +913,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev)

/* Release input device (IR) resources */
#ifdef SMS_RC_SUPPORT_SUBSYS
+ /* Release input device (IR) resources */
sms_ir_exit(coredev);
#endif /*SMS_RC_SUPPORT_SUBSYS*/
smscore_notify_clients(coredev);
@@ -737,7 +939,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev)

sms_info("waiting for %d buffer(s)",
coredev->num_buffers - num_buffers);
+ kmutex_unlock(&g_smscore_deviceslock);
msleep(100);
+ kmutex_lock(&g_smscore_deviceslock);
}

sms_info("freed %d buffers", num_buffers);
@@ -800,30 +1004,106 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
}

static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
- /*Stellar NOVA A0 Nova B0 VEGA*/
+/*Stellar, NOVA A0, Nova B0, VEGA, VENICE, MING, PELE, RIO, DENVER_1530, DENVER_2160*/
/*DVBT*/
- {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" },
/*DVBH*/
- {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvbh_rio.inp", "none", "none" },
/*TDMB*/
- {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
+{ "none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none", "none", "none", "none", "none", "none", "tdmb_denver.inp" },
/*DABIP*/
- {"none", "none", "none", "none"},
- /*BDA*/
- {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" },
+/*DVBT_BDA*/
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" },
/*ISDBT*/
- {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
- /*ISDBTBDA*/
- {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+{ "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" }, +/*ISDBT_BDA*/
+{ "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" },
/*CMMB*/
- {"none", "none", "none", "cmmb_vega_12mhz.inp"}
+{ "none", "none", "none", "cmmb_vega_12mhz.inp", "cmmb_venice_12mhz.inp", "cmmb_ming_app.inp", "none", "none", "none", "none" },
+/*RAW - not supported*/
+{ "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" },
+/*FM*/
+{ "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" },
+/*FM_BDA*/
+{ "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" },
+/*ATSC*/
+{ "none", "none", "none", "none", "none", "none", "none", "none", "atsc_denver.inp", "none" }
};

-static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
- int mode, enum sms_device_type_st type)
+/**
+ * get firmware file name from one of the two mechanisms : sms_boards or
+ * smscore_fw_lkup.
+
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param mode requested mode of operation
+ * @param lookup if 1, always get the fw filename from smscore_fw_lkup
+ * table. if 0, try first to get from sms_boards
+ *
+ * @return 0 on success, <0 on error.
+ */
+char *smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, int lookup) {
+ char **fw;
+ int board_id = smscore_get_board_id(coredev);
+ enum sms_device_type_st type =
smscore_registry_gettype(coredev->devpath);
+
+ if ( (board_id == SMS_BOARD_UNKNOWN) ||
+ (lookup == 1) ) {
+ sms_debug("trying to get fw name from lookup table mode %d type %d",
mode, type);
+ return smscore_fw_lkup[mode][type];
+ }
+
+ sms_debug("trying to get fw name from sms_boards board_id %d mode %d",
board_id, mode);
+ fw = sms_get_board(board_id)->fw;
+ if (fw == NULL) {
+ sms_debug("cannot find fw name in sms_boards, getting from lookup
table mode %d type %d", mode, type);
+ return smscore_fw_lkup[mode][type];
+ }
+
+ if (fw[mode] == NULL) {
+ sms_debug("cannot find fw name in sms_boards, getting from lookup
table mode %d type %d", mode, type);
+ return smscore_fw_lkup[mode][type];
+ }
+
+ return fw[mode];
+}
+
+/**
+ * send init device request and wait for response
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_init_device(struct smscore_device_t *coredev, int mode)
{
- char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
- return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+ void* buffer;
+ struct SmsMsgData_S *msg;
+ int rc = 0;
+
+ buffer = kmalloc(sizeof(struct SmsMsgData_S) +
+ SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+ if (!buffer) {
+ sms_err("Could not allocate buffer for "
+ "init device message.");
+ return -ENOMEM;
+ }
+
+ msg = (struct SmsMsgData_S *)SMS_ALIGN_ADDRESS(buffer);
+ SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+ sizeof(struct SmsMsgData_S));
+ msg->msgData[0] = mode;
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+ rc = smscore_sendrequest_and_wait(coredev, msg,
+ msg->xMsgHeader. msgLength,
+ &coredev->init_device_done);
+
+ kfree(buffer);
+ return rc;
}

/**
@@ -838,13 +1118,11 @@ static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
*/
int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) {
- void *buffer;
int rc = 0;
- enum sms_device_type_st type;

sms_debug("set device mode to %d", mode);
if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
- if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >=
SMSHOSTLIB_DEVMD_RAW_TUNER) {
+ if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >= SMSHOSTLIB_DEVMD_MAX) {
sms_err("invalid mode specified %d", mode); return -EINVAL;
}
@@ -865,56 +1143,35 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
}

if (!(coredev->modes_supported & (1 << mode))) {
- char *fw_filename;
+ rc = smscore_load_firmware_from_file(coredev, mode, 0, NULL);

- type = smscore_registry_gettype(coredev->devpath);
- fw_filename = sms_get_fw_name(coredev, mode, type);
-
- rc = smscore_load_firmware_from_file(coredev,
- fw_filename, NULL);
+ /*
+ * try again with the default firmware -
+ * get the fw filename from look-up table
+ */
if (rc < 0) {
- sms_debug("error %d loading firmware: %s, "
- "trying again with default firmware",
- rc, fw_filename);
-
- /* try again with the default firmware */
- fw_filename = smscore_fw_lkup[mode][type];
- rc = smscore_load_firmware_from_file(coredev,
- fw_filename, NULL);
+ sms_debug("error %d loading firmware, "
+ "trying again with default firmware", rc);
+ rc = smscore_load_firmware_from_file(coredev, mode, 1, NULL);
+ }

if (rc < 0) {
- sms_debug("error %d loading firmware", rc);
+ sms_debug("error %d loading firmware", rc);
return rc;
}
- }
- sms_log("firmware download success: %s", fw_filename);
- } else
- sms_info("mode %d supported by running "
- "firmware", mode);

- buffer = kmalloc(sizeof(struct SmsMsgData_S) +
- SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
- if (buffer) {
- struct SmsMsgData_S *msg =
- (struct SmsMsgData_S *)
- SMS_ALIGN_ADDRESS(buffer);
-
- SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
- sizeof(struct SmsMsgData_S));
- msg->msgData[0] = mode;
-
- rc = smscore_sendrequest_and_wait(
- coredev, msg, msg->xMsgHeader.msgLength,
- &coredev->init_device_done);
-
- kfree(buffer);
+ sms_info("firmware download success");
} else {
- sms_err("Could not allocate buffer for "
- "init device message.");
- rc = -ENOMEM;
+ sms_info("mode %d is already supported by running "
+ "firmware", mode);
+ }
+
+ rc = smscore_init_device(coredev, mode);
+ if (rc < 0) {
+ sms_err("device init failed, rc %d.", rc);
}
} else {
- if (mode < SMSHOSTLIB_DEVMD_DVBT || mode > SMSHOSTLIB_DEVMD_DVBT_BDA)
{
+ if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >= SMSHOSTLIB_DEVMD_MAX) {
sms_err("invalid mode specified %d", mode); return -EINVAL;
}
@@ -943,6 +1200,58 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
sms_err("return error code %d.", rc);
return rc;
}
+EXPORT_SYMBOL_GPL(smscore_set_device_mode);
+
+/**
+ * configures device features according to voard configuration structure.
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_configure_board(struct smscore_device_t *coredev) {
+ struct sms_board* board;
+
+ board = sms_get_board(coredev->board_id);
+ if (!board)
+ {
+ sms_err("no board configuration exist.");
+ return -1;
+ }
+
+ if (board->mtu)
+ {
+ struct SmsMsgData_S MtuMsg;
+ sms_debug("set max transmit unit %d", board->mtu);
+
+ MtuMsg.xMsgHeader.msgSrcId = 0;
+ MtuMsg.xMsgHeader.msgDstId = HIF_TASK;
+ MtuMsg.xMsgHeader.msgFlags = 0;
+ MtuMsg.xMsgHeader.msgType = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
+ MtuMsg.xMsgHeader.msgLength = sizeof(MtuMsg);
+ MtuMsg.msgData[0] = board->mtu;
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)&MtuMsg);
+ coredev->sendrequest_handler(coredev->context, &MtuMsg,
sizeof(MtuMsg));
+ }
+
+ if (board->crystal)
+ {
+ struct SmsMsgData_S CrysMsg;
+ sms_debug("set crystal value %d", board->crystal);
+
+ SMS_INIT_MSG(&CrysMsg.xMsgHeader,
+ MSG_SMS_NEW_CRYSTAL_REQ,
+ sizeof(CrysMsg));
+ CrysMsg.msgData[0] = board->crystal;
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_S *)&CrysMsg);
+ coredev->sendrequest_handler(coredev->context, &CrysMsg,
sizeof(CrysMsg));
+ }
+
+ return 0;
+}

/**
* calls device handler to get current mode of operation
@@ -1099,6 +1408,13 @@ void smscore_onresponse(struct smscore_device_t *coredev,
case MSG_SW_RELOAD_EXEC_RES:
sms_debug("MSG_SW_RELOAD_EXEC_RES"); break;
+ case MSG_SMS_DATA_VALIDITY_RES:
+ {
+ struct SmsMsgData_S *validity = (struct SmsMsgData_S *) phdr;
+ sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
validity->msgData[0]);
+ complete(&coredev->data_validity_done);
+ break;
+ }
case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES"); complete(&coredev->trigger_done);
@@ -1188,8 +1504,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer);
*/
void smscore_putbuffer(struct smscore_device_t *coredev,
struct smscore_buffer_t *cb) {
- wake_up_interruptible(&coredev->buffer_mng_waitq);
list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
+ wake_up_interruptible(&coredev->buffer_mng_waitq);
}
EXPORT_SYMBOL_GPL(smscore_putbuffer);

Signature · 1 line
1.7.4.1
#1 lore raw

Em 20-09-2011 07:31, Doron Cohen escreveu:

Quoted 207 lines

Hi,
This patch step Improve firmware load and reload mechanism in order to support new siano devices and match all existing devices.

Thanks,
Doron Cohen

-----------------------

Quoted 1 line

From 59062b9fbc2f3c28cbb1ec014c6ed5a3e065a7de Mon Sep 17 00:00:00 2001

From: Doron Cohen <[email protected]>
Date: Tue, 20 Sep 2011 08:22:29 +0300
Subject: [PATCH 16/21] Improve firmware load and reload mechanism in order to support new siano devices and match all existing devices.

---
 drivers/media/dvb/siano/smscoreapi.c |  530
+++++++++++++++++++++++++++-------
 1 files changed, 423 insertions(+), 107 deletions(-)
drivers/media/dvb/siano/smscoreapi.c +1 -0
index db24391..e50e356 100644
@@ -312,6 +312,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer,
 void *common_buffer,
 	cb->p = buffer;
 	cb->offset_in_common = buffer - (u8 *) common_buffer;
 	cb->phys = common_buffer_phys + cb->offset_in_common;
+	cb->offset=0;
 
 	return cb;

}

drivers/media/dvb/siano/smscoreapi.c +1 -0
@@ -352,6 +353,7 @@ int smscore_register_device(struct
 smsdevice_params_t *params,
 	/* init completion events */
 	init_completion(&dev->version_ex_done);
 	init_completion(&dev->data_download_done);
+	init_completion(&dev->data_validity_done);
 	init_completion(&dev->trigger_done);
 	init_completion(&dev->init_device_done);
drivers/media/dvb/siano/smscoreapi.c +1 -0
 	init_completion(&dev->reload_start_done);
@@ -360,6 +362,7 @@ int smscore_register_device(struct
 smsdevice_params_t *params,
 	init_completion(&dev->gpio_set_level_done);
 	init_completion(&dev->gpio_get_level_done);
 	init_completion(&dev->ir_init_done);
+	init_completion(&dev->device_ready_done);
 
 	/* Buffer management */
drivers/media/dvb/siano/smscoreapi.c +7 -1
 	init_waitqueue_head(&dev->buffer_mng_waitq);
@@ -426,7 +429,13 @@ EXPORT_SYMBOL_GPL(smscore_register_device);
 
 static int smscore_sendrequest_and_wait(struct smscore_device_t
 *coredev,
 		void *buffer, size_t size, struct completion *completion) {
-	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+	int rc;
+
+	if (completion == NULL)
+		return -EINVAL;
+	init_completion(completion);
+
+	rc = coredev->sendrequest_handler(coredev->context, buffer, size);
 	if (rc < 0) {
 		sms_info("sendrequest returned error %d", rc);
drivers/media/dvb/siano/smscoreapi.c +2 -1
 		return rc;
@@ -535,7 +544,8 @@ static int smscore_load_firmware_family2(struct
 smscore_device_t *coredev,
 {
 	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
 	struct SmsMsgHdr_S *msg;
-	u32 mem_address;
+	u32 mem_address,  calc_checksum = 0;
+	u32 i, *ptr;
 	u8 *payload = firmware->Payload;
 	int rc = 0;
drivers/media/dvb/siano/smscoreapi.c +48 -25
 	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
@@ -563,9 +573,17 @@ static int smscore_load_firmware_family2(struct
 smscore_device_t *coredev,
 		rc = smscore_sendrequest_and_wait(coredev, msg,
 						  msg->msgLength,
 						  &coredev->reload_start_done);
+
+		if (rc < 0) {				
+			sms_err("device reload failed, rc %d", rc);
+			goto exit_fw_download;
+		}
+
 		mem_address = *(u32 *) &payload[20];
 	}
 
+	for (i = 0, ptr = (u32*)firmware->Payload; i < firmware->Length/4 ; i
++, ptr++)
+		calc_checksum += *ptr;
 	while (size && rc >= 0) {
 		struct SmsDataDownload_S *DataMsg =
 			(struct SmsDataDownload_S *) msg;
@@ -578,14 +596,9 @@ static int smscore_load_firmware_family2(struct
 smscore_device_t *coredev,
 		DataMsg->MemAddr = mem_address;
 		memcpy(DataMsg->Payload, payload, payload_size);
 
-		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
-		    (coredev->mode == SMSHOSTLIB_DEVMD_NONE))
-			rc = coredev->sendrequest_handler(
-				coredev->context, DataMsg,
-				DataMsg->xMsgHeader.msgLength);
-		else
-			rc = smscore_sendrequest_and_wait(
-				coredev, DataMsg,
+
+	
+		rc = smscore_sendrequest_and_wait(coredev, DataMsg,
 				DataMsg->xMsgHeader.msgLength,
 				&coredev->data_download_done);
@@ -594,44 +607,63 @@ static int smscore_load_firmware_family2(struct
 smscore_device_t *coredev,
 		mem_address += payload_size;
 	}
 
-	if (rc >= 0) {
+	if (rc < 0) 		
+		goto exit_fw_download;
+
+	sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
 calc_checksum);
+	SMS_INIT_MSG(msg, MSG_SMS_DATA_VALIDITY_REQ,
+			sizeof(struct SmsMsgHdr_S) +
+			sizeof(u32) * 3);
+	((struct SmsMsgData_S *)msg)->msgData[0] = firmware->StartAddress;
+		/* Entry point */
+	((struct SmsMsgData_S *)msg)->msgData[1] = firmware->Length;
+	((struct SmsMsgData_S *)msg)->msgData[2] = 0; /* Regular checksum*/
+	smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+	rc = smscore_sendrequest_and_wait(coredev, msg,	((struct SmsMsgData_S
 *)msg)->xMsgHeader.msgLength, &coredev->data_validity_done);
+	if (rc < 0) 		
+		goto exit_fw_download;
+
+
 		if (coredev->mode == SMSHOSTLIB_DEVMD_NONE) {
 			struct SmsMsgData_S *TriggerMsg =
 				(struct SmsMsgData_S *) msg;
 
+		        sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
 			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
 				     sizeof(struct SmsMsgHdr_S) +
 				     sizeof(u32) * 5);
 
 			TriggerMsg->msgData[0] = firmware->StartAddress;
 						/* Entry point */
-			TriggerMsg->msgData[1] = 5; /* Priority */
+		TriggerMsg->msgData[1] = 6; /* Priority */
 			TriggerMsg->msgData[2] = 0x200; /* Stack size */
 			TriggerMsg->msgData[3] = 0; /* Parameter */
 			TriggerMsg->msgData[4] = 4; /* Task ID */
 
-			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
-				rc = coredev->sendrequest_handler(
-					coredev->context, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength);
-				msleep(100);
-			} else
-				rc = smscore_sendrequest_and_wait(
-					coredev, TriggerMsg,
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+		rc = smscore_sendrequest_and_wait(coredev,
+			TriggerMsg,
 					TriggerMsg->xMsgHeader.msgLength,
 					&coredev->trigger_done);
 		} else {
 			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
 				     sizeof(struct SmsMsgHdr_S));
-
-			rc = coredev->sendrequest_handler(coredev->context,
-							  msg, msg->msgLength);
-		}
-		msleep(500);
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+		rc = coredev->sendrequest_handler(coredev->context, msg,
+				msg->msgLength);
 	}
 
-	sms_debug("rc=%d, postload=%p ", rc,
-		  coredev->postload_handler);
+	if (rc < 0)
+		goto exit_fw_download;
+			
+	/*
+	 * backward compatibility - wait to device_ready_done for
+	 * not more than 400 ms
+	 */
+	msleep(400);
+
+exit_fw_download:
+	sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler);
drivers/media/dvb/siano/smscoreapi.c +0 -0
 	kfree(msg);
@@ -653,42 +685,211 @@ static int smscore_load_firmware_family2(struct
 smscore_device_t *coredev,
  * @return 0 on success, <0 on error.
  */
 static int smscore_load_firmware_from_file(struct smscore_device_t

drivers/media/dvb/siano/smscoreapi.c static int smscore_load_firmware_family2(struct · line 695

Quoted 10 lines
drivers/media/dvb/siano/smscoreapi.c +5 -3
 *coredev,
-					   char *filename,
-					   loadfirmware_t loadfirmware_handler)
-{
+		int mode, int lookup, loadfirmware_t loadfirmware_handler) {
 	int rc = -ENOENT;
+	u8 *fw_buf;
+	u32 fw_buf_size;
+
+#ifdef REQUEST_FIRMWARE_SUPPORTED

NACK. request_firmware should always be there for devices that have firmware.

Quoted 232 lines
drivers/media/dvb/siano/smscoreapi.c +42 -14
 	const struct firmware *fw;
-	u8 *fw_buffer;
 
-	if (loadfirmware_handler == NULL && !(coredev->device_flags &
-					      SMS_DEVICE_FAMILY2))
+	char* fw_filename = smscore_get_fw_filename(coredev, mode, lookup);
+	if (!strcmp(fw_filename,"none"))
+		return -ENOENT;
+
+	if (loadfirmware_handler == NULL && !(coredev->device_flags
+			& SMS_DEVICE_FAMILY2))
 		return -EINVAL;
 
-	rc = request_firmware(&fw, filename, coredev->device);
+	rc = request_firmware(&fw, fw_filename, coredev->device);
 	if (rc < 0) {
-		sms_info("failed to open \"%s\"", filename);
+		sms_info("failed to open \"%s\"", fw_filename);
 		return rc;
 	}
-	sms_info("read FW %s, size=%zd", filename, fw->size);
-	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+	sms_info("read fw %s, buffer size=0x%x", fw_filename, fw->size);
+	fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
 			    GFP_KERNEL | GFP_DMA);
-	if (fw_buffer) {
-		memcpy(fw_buffer, fw->data, fw->size);
+	if (!fw_buf) {
+		sms_info("failed to allocate firmware buffer");
+		return -ENOMEM;
+	}
+	memcpy(fw_buf, fw->data, fw->size);
+	fw_buf_size = fw->size;
+#else
+	if (!coredev->fw_buf) {
+		sms_info("missing fw file buffer");
+		return -EINVAL;
+	}
+	fw_buf = coredev->fw_buf;
+	fw_buf_size = coredev->fw_buf_size;
+#endif
 
 		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
-		      smscore_load_firmware_family2(coredev,
-						    fw_buffer,
-						    fw->size) :
-		      loadfirmware_handler(coredev->context,
-					   fw_buffer, fw->size);
+		smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
+		: loadfirmware_handler(coredev->context, fw_buf,
+		fw_buf_size);
+
+	kfree(fw_buf);
+
+#ifdef REQUEST_FIRMWARE_SUPPORTED
+	release_firmware(fw);
+#else
+	coredev->fw_buf = NULL;
+	coredev->fw_buf_size = 0;
+#endif
+	return rc;
+}
+
+/**
+ * Send chunk of firmware data using SMS MSGs
+ * The motivation is to eliminate the need of big memory allocation in

kernel for firmware
+ * download.
+ *
+ * @param coredev pointer to a coredev object returned by

+ *                smscore_register_device
+ * @param buffer  pointer to a buffer
+ * @param size    size of buffer

+ *
+ * @return 0 on success, <0 on error.
+ */

drivers/media/dvb/siano/smscoreapi.c +48 -1
+int smscore_send_fw_chunk(struct smscore_device_t *coredev,
+		void *buffer, size_t size) 
+{
+
+	struct SmsMsgHdr_S *msg;
+	int rc = 0;
+	int offset = 0;
+	
+	if (buffer == NULL)
+	{
+		sms_debug("Error: NULL buffer");
+		return -1;
+	}
+	
+	/* First chunk */
+	if (coredev->start_address == 0)
+	{
+		struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+		coredev->start_address = le32_to_cpu(firmware->StartAddress);
+		coredev->current_address = coredev->start_address;
+		offset = 12;
+		size -= 12;
+		
+		if (coredev->preload_handler) 
+		{
+			rc = coredev->preload_handler(coredev->context);
+			if (rc < 0)
+				return rc;
+		}
+	}
+		
+	/* PAGE_SIZE buffer shall be enough and dma aligned */
+	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!msg)
+		return -ENOMEM;
+		
+	while (size && rc >= 0) {
+		int payload_size;
+		struct SmsDataDownload_S *DataMsg;
+		sms_debug("sending MSG_SMS_DATA_DOWNLOAD_REQ");
+		DataMsg = (struct SmsDataDownload_S *) msg;
+		payload_size = min((int)size, SMS_MAX_PAYLOAD_SIZE);
 
-		kfree(fw_buffer);
+		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+				(u16) (sizeof(struct SmsMsgHdr_S) +
+						sizeof(u32) + payload_size));
+
+		DataMsg->MemAddr = coredev->current_address;
+		copy_from_user(DataMsg->Payload, (u8*)(buffer + offset),

payload_size);

drivers/media/dvb/siano/smscoreapi.c +87 -3
+
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+		rc = smscore_sendrequest_and_wait(coredev, DataMsg,
+			DataMsg->xMsgHeader.msgLength,
+			&coredev->data_download_done);
+
+		size -= payload_size;
+		offset += payload_size;
+		coredev->current_address += payload_size;
+	}
+
+	kfree(msg);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(smscore_send_fw_chunk);
+
+
+/**
+ * Send last chunk of firmware data using SMS MSGs
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param buffer  pointer to a buffer
+ * @param size    size of buffer
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_send_last_fw_chunk(struct smscore_device_t *coredev,
+		void *buffer, size_t size) 
+{
+	int rc = 0;
+	struct SmsMsgHdr_S *msg;
+	
+	rc = smscore_send_fw_chunk(coredev, buffer, size);
+	if (rc < 0)
+		return rc;
+	
+	/* PAGE_SIZE buffer shall be enough and dma aligned */
+	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!msg)
+		return -ENOMEM;
+	
+	if (coredev->mode == SMSHOSTLIB_DEVMD_NONE) {
+		struct SmsMsgData_S *TriggerMsg =
+				(struct SmsMsgData_S *) msg;
+
+		sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+		SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+				sizeof(struct SmsMsgHdr_S) +
+				sizeof(u32) * 5);
+
+		TriggerMsg->msgData[0] = coredev->start_address;
+		/* Entry point */
+		TriggerMsg->msgData[1] = 6; /* Priority */
+		TriggerMsg->msgData[2] = 0x200; /* Stack size */
+		TriggerMsg->msgData[3] = 0; /* Parameter */
+		TriggerMsg->msgData[4] = 4; /* Task ID */
+
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+		rc = smscore_sendrequest_and_wait(coredev,
+			TriggerMsg,
+			TriggerMsg->xMsgHeader.msgLength,
+			&coredev->trigger_done);
 	} else {
-		sms_info("failed to allocate firmware buffer");
-		rc = -ENOMEM;
+		SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+				sizeof(struct SmsMsgHdr_S));
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+		rc = coredev->sendrequest_handler(coredev->context, msg,
+				msg->msgLength);
 	}
 
-	release_firmware(fw);
+	/* clear start_address */
+	coredev->start_address = 0;
+
+	if (rc < 0)
+		goto exit_fw_download;
+			
+	/*
+	 * backward compatibility - wait to device_ready_done for
+	 * not more than 400 ms
+	 */
+	wait_for_completion_timeout(&coredev->device_ready_done,
+			msecs_to_jiffies(400));		
+
+exit_fw_download:
+	sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler);
+
+	kfree(msg);
 
 	return rc;
 }
@@ -712,6 +913,7 @@ void smscore_unregister_device(struct
 smscore_device_t *coredev)
 
 	/* Release input device (IR) resources */
 #ifdef SMS_RC_SUPPORT_SUBSYS
+	/* Release input device (IR) resources */
 	sms_ir_exit(coredev);
 #endif /*SMS_RC_SUPPORT_SUBSYS*/
drivers/media/dvb/siano/smscoreapi.c +0 -0
 	smscore_notify_clients(coredev);

drivers/media/dvb/siano/smscoreapi.c void smscore_unregister_device(struct · line 943

Quoted 5 lines
drivers/media/dvb/siano/smscoreapi.c +1 -0
@@ -737,7 +939,9 @@ void smscore_unregister_device(struct
 smscore_device_t *coredev)
 
 		sms_info("waiting for %d buffer(s)",
 			 coredev->num_buffers - num_buffers);
+		kmutex_unlock(&g_smscore_deviceslock);

kmutex_unlock??? Don't re-define a function that already exists at the Linux Kernel.

Quoted 333 lines
drivers/media/dvb/siano/smscoreapi.c +1 -0
 		msleep(100);
+		kmutex_lock(&g_smscore_deviceslock);
 	}
 
drivers/media/dvb/siano/smscoreapi.c +1 -1
 	sms_info("freed %d buffers", num_buffers);
@@ -800,30 +1004,106 @@ static int smscore_detect_mode(struct
 smscore_device_t *coredev)
 }
 
 static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
-	/*Stellar		NOVA A0		Nova B0		VEGA*/
+/*Stellar, NOVA A0, Nova B0, VEGA, VENICE, MING, PELE, RIO,

DENVER_1530, DENVER_2160*/

drivers/media/dvb/siano/smscoreapi.c +1 -1
 	/*DVBT*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none",

"none", "none", "none", "dvb_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +1 -1
 	/*DVBH*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none",

"none", "none", "none", "dvbh_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +1 -1
 	/*TDMB*/
-	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
+{ "none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none",

"none", "none", "none", "none", "none", "tdmb_denver.inp" },

drivers/media/dvb/siano/smscoreapi.c +1 -3
 	/*DABIP*/
-	{"none", "none", "none", "none"},
-	/*BDA*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+{ "none", "none", "none", "none", "none", "none", "none", "none",

"none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*DVBT_BDA*/
+{ "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none",

"none", "none", "none", "dvb_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +1 -3
 	/*ISDBT*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*ISDBTBDA*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+{ "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none",

"none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*ISDBT_BDA*/
+{ "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none",

"none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +1 -1
 	/*CMMB*/
-	{"none", "none", "none", "cmmb_vega_12mhz.inp"}
+{ "none", "none", "none", "cmmb_vega_12mhz.inp",

"cmmb_venice_12mhz.inp", "cmmb_ming_app.inp", "none", "none", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*RAW - not supported*/
+{ "none", "none", "none", "none", "none", "none", "none", "none",

"none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*FM*/
+{ "none", "none", "fm_radio.inp", "none", "none", "none", "none",

"fm_radio_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*FM_BDA*/
+{ "none", "none", "fm_radio.inp", "none", "none", "none", "none",

"fm_radio_rio.inp", "none", "none" },

drivers/media/dvb/siano/smscoreapi.c +2 -0
+/*ATSC*/
+{ "none", "none", "none", "none", "none", "none", "none", "none",

"atsc_denver.inp", "none" }
};

drivers/media/dvb/siano/smscoreapi.c +2 -2
-static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
-				    int mode, enum sms_device_type_st type)
+/**
+ * get firmware file name from one of the two mechanisms : sms_boards

or
+ * smscore_fw_lkup.

drivers/media/dvb/siano/smscoreapi.c +10 -0
+
+ * @param coredev pointer to a coredev object returned by
+ * 		  smscore_register_device
+ * @param mode requested mode of operation
+ * @param lookup if 1, always get the fw filename from smscore_fw_lkup 
+ * 	 table. if 0, try first to get from sms_boards
+ *
+ * @return 0 on success, <0 on error.
+ */
+char *smscore_get_fw_filename(struct smscore_device_t *coredev, int

mode, int lookup) {

drivers/media/dvb/siano/smscoreapi.c +3 -0
+	char **fw;
+	int board_id = smscore_get_board_id(coredev);
+	enum sms_device_type_st type =

smscore_registry_gettype(coredev->devpath);

drivers/media/dvb/siano/smscoreapi.c +4 -0
+
+	if ( (board_id == SMS_BOARD_UNKNOWN) || 
+	     (lookup == 1) ) {
+		sms_debug("trying to get fw name from lookup table mode %d type %d",

mode, type);

drivers/media/dvb/siano/smscoreapi.c +4 -0
+		return smscore_fw_lkup[mode][type];
+	}
+	
+	sms_debug("trying to get fw name from sms_boards board_id %d mode %d",

board_id, mode);

drivers/media/dvb/siano/smscoreapi.c +3 -0
+	fw = sms_get_board(board_id)->fw;
+	if (fw == NULL) {
+		sms_debug("cannot find fw name in sms_boards, getting from lookup

table mode %d type %d", mode, type);

drivers/media/dvb/siano/smscoreapi.c +5 -0
+		return smscore_fw_lkup[mode][type];
+	}
+
+	if (fw[mode] == NULL) {
+		sms_debug("cannot find fw name in sms_boards, getting from lookup

table mode %d type %d", mode, type);

drivers/media/dvb/siano/smscoreapi.c +41 -5
+		return smscore_fw_lkup[mode][type];
+	}
+
+	return fw[mode];
+}
+
+/**
+ * send init device request and wait for response
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_init_device(struct smscore_device_t *coredev, int mode)
 {
-	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
-	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+	void* buffer;
+	struct SmsMsgData_S *msg;
+	int rc = 0;
+
+	buffer = kmalloc(sizeof(struct SmsMsgData_S) +
+			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
+		sms_err("Could not allocate buffer for "
+				"init device message.");
+		return -ENOMEM;
+	}
+
+	msg = (struct SmsMsgData_S *)SMS_ALIGN_ADDRESS(buffer);
+	SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+			sizeof(struct SmsMsgData_S));
+	msg->msgData[0] = mode;
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg);
+	rc = smscore_sendrequest_and_wait(coredev, msg,
+			msg->xMsgHeader. msgLength,
+			&coredev->init_device_done);
+
+	kfree(buffer);
+	return rc;
 }
 
 /**
@@ -838,13 +1118,11 @@ static inline char *sms_get_fw_name(struct
 smscore_device_t *coredev,
  */
 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 {
-	void *buffer;
 	int rc = 0;
-	enum sms_device_type_st type;
 
 	sms_debug("set device mode to %d", mode);
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >=
 SMSHOSTLIB_DEVMD_RAW_TUNER) {
+		if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >= SMSHOSTLIB_DEVMD_MAX) {
 			sms_err("invalid mode specified %d", mode);
drivers/media/dvb/siano/smscoreapi.c +19 -40
 			return -EINVAL;
 		}
@@ -865,56 +1143,35 @@ int smscore_set_device_mode(struct
 smscore_device_t *coredev, int mode)
 		}
 
 		if (!(coredev->modes_supported & (1 << mode))) {
-			char *fw_filename;
+			rc = smscore_load_firmware_from_file(coredev, mode, 0, NULL);
 
-			type = smscore_registry_gettype(coredev->devpath);
-			fw_filename = sms_get_fw_name(coredev, mode, type);
-
-			rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
+			/* 
+			* try again with the default firmware -
+			* get the fw filename from look-up table
+			*/
 			if (rc < 0) {
-				sms_debug("error %d loading firmware: %s, "
-					 "trying again with default firmware",
-					 rc, fw_filename);
-
-				/* try again with the default firmware */
-				fw_filename = smscore_fw_lkup[mode][type];
-				rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
+				sms_debug("error %d loading firmware, "
+					"trying again with default firmware", rc);
+				rc = smscore_load_firmware_from_file(coredev, mode, 1, NULL);
+			}
 
 				if (rc < 0) {
-				        sms_debug("error %d loading firmware", rc);
+				sms_debug("error %d loading firmware", rc);
 					return rc;
 				}
-			}
-			sms_log("firmware download success: %s", fw_filename);
-		} else
-			sms_info("mode %d supported by running "
-				 "firmware", mode);
 
-		buffer = kmalloc(sizeof(struct SmsMsgData_S) +
-				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
-		if (buffer) {
-			struct SmsMsgData_S *msg =
-				(struct SmsMsgData_S *)
-					SMS_ALIGN_ADDRESS(buffer);
-
-			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
-				     sizeof(struct SmsMsgData_S));
-			msg->msgData[0] = mode;
-
-			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->xMsgHeader.msgLength,
-				&coredev->init_device_done);
-
-			kfree(buffer);
+			sms_info("firmware download success");
 		} else {
-			sms_err("Could not allocate buffer for "
-				"init device message.");
-			rc = -ENOMEM;
+			sms_info("mode %d is already supported by running "
+					"firmware", mode);
+			}
+
+		rc = smscore_init_device(coredev, mode);
+		if (rc < 0) {
+			sms_err("device init failed, rc %d.", rc);
 		}
 	} else {
-		if (mode < SMSHOSTLIB_DEVMD_DVBT || mode > SMSHOSTLIB_DEVMD_DVBT_BDA)
 {
+		if (mode < SMSHOSTLIB_DEVMD_DVBT || mode >= SMSHOSTLIB_DEVMD_MAX) {
 			sms_err("invalid mode specified %d", mode);
drivers/media/dvb/siano/smscoreapi.c +4 -0
 			return -EINVAL;
 		}
@@ -943,6 +1200,58 @@ int smscore_set_device_mode(struct
 smscore_device_t *coredev, int mode)
 		sms_err("return error code %d.", rc);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(smscore_set_device_mode);
+
+/**
+ * configures device features according to voard configuration

structure.
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */

drivers/media/dvb/siano/smscoreapi.c +24 -0
+int smscore_configure_board(struct smscore_device_t *coredev) {
+	struct sms_board* board;
+
+	board = sms_get_board(coredev->board_id);
+	if (!board)
+	{
+		sms_err("no board configuration exist.");
+		return -1;
+	}
+	
+	if (board->mtu)
+	{
+		struct SmsMsgData_S MtuMsg;
+		sms_debug("set max transmit unit %d", board->mtu);
+
+		MtuMsg.xMsgHeader.msgSrcId = 0;
+		MtuMsg.xMsgHeader.msgDstId = HIF_TASK;
+		MtuMsg.xMsgHeader.msgFlags = 0;
+		MtuMsg.xMsgHeader.msgType = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
+		MtuMsg.xMsgHeader.msgLength = sizeof(MtuMsg);
+		MtuMsg.msgData[0] = board->mtu;
+
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)&MtuMsg);
+		coredev->sendrequest_handler(coredev->context, &MtuMsg,

sizeof(MtuMsg));

drivers/media/dvb/siano/smscoreapi.c +14 -0
+	}
+
+	if (board->crystal)
+	{
+		struct SmsMsgData_S CrysMsg;
+		sms_debug("set crystal value %d", board->crystal);
+
+		SMS_INIT_MSG(&CrysMsg.xMsgHeader, 
+				MSG_SMS_NEW_CRYSTAL_REQ,
+				sizeof(CrysMsg));
+		CrysMsg.msgData[0] = board->crystal;
+
+		smsendian_handle_tx_message((struct SmsMsgHdr_S *)&CrysMsg);
+		coredev->sendrequest_handler(coredev->context, &CrysMsg,

sizeof(CrysMsg));

drivers/media/dvb/siano/smscoreapi.c +11 -0
+	}
+
+	return 0;
+}
 
 /**
  * calls device handler to get current mode of operation
@@ -1099,6 +1408,13 @@ void smscore_onresponse(struct smscore_device_t
 *coredev,
 		case MSG_SW_RELOAD_EXEC_RES:
 			sms_debug("MSG_SW_RELOAD_EXEC_RES");
 			break;
+		case MSG_SMS_DATA_VALIDITY_RES:
+		{
+			struct SmsMsgData_S *validity = (struct SmsMsgData_S *) phdr;			
+			sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
 validity->msgData[0]);
+			complete(&coredev->data_validity_done);
+			break;
+		}
 		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
drivers/media/dvb/siano/smscoreapi.c +1 -1
 			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
 			complete(&coredev->trigger_done);
@@ -1188,8 +1504,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer);
  */
 void smscore_putbuffer(struct smscore_device_t *coredev,
 		struct smscore_buffer_t *cb) {
-	wake_up_interruptible(&coredev->buffer_mng_waitq);
 	list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
+	wake_up_interruptible(&coredev->buffer_mng_waitq);
 }
 EXPORT_SYMBOL_GPL(smscore_putbuffer);