static int mpq_tspp_remove_accept_all_filter(int channel_id, enum tspp_source source) { struct tspp_filter tspp_filter; int tsif = TSPP_GET_TSIF_NUM(channel_id); int ret; MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n", __func__, channel_id, source); if (mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag == 0) { MPQ_DVB_DBG_PRINT("%s: accept all filter doesn't exist\n", __func__); return 0; } tspp_filter.priority = TSPP_LAST_HW_FILTER_INDEX; ret = tspp_remove_filter(0, channel_id, &tspp_filter); if (!ret) { mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag = 0; MPQ_DVB_DBG_PRINT( "%s: accept all filter removed successfully\n", __func__); } return ret; }
static int mpq_tspp_add_null_blocking_filters(int channel_id, enum tspp_source source) { struct tspp_filter tspp_filter; int ret = 0; int i, j; u16 full_pid_mask = 0x1FFF; u8 mask_shift; u8 pid_shift; int tsif = TSPP_GET_TSIF_NUM(channel_id); MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n", __func__, channel_id, source); tspp_filter.mode = TSPP_MODE_RAW; tspp_filter.source = source; tspp_filter.decrypt = 0; for (i = 0; i < TSPP_BLOCK_NULLS_FILTERS_NUM; i++) { tspp_filter.priority = mpq_tspp_allocate_hw_filter_index(tsif); if (tspp_filter.priority != i) { MPQ_DVB_ERR_PRINT( "%s: got unexpected HW index %d, expected %d\n", __func__, tspp_filter.priority, i); ret = -1; break; } mask_shift = (TSPP_BLOCK_NULLS_FILTERS_NUM - 1 - i); pid_shift = (TSPP_BLOCK_NULLS_FILTERS_NUM - i); tspp_filter.mask = ((full_pid_mask >> mask_shift) << mask_shift); tspp_filter.pid = ((full_pid_mask >> pid_shift) << pid_shift); if (tspp_add_filter(0, channel_id, &tspp_filter)) { ret = -1; break; } } if (ret) { for (j = 0; j < i; j++) { tspp_filter.priority = j; mpq_tspp_release_hw_filter_index(tsif, j); tspp_remove_filter(0, channel_id, &tspp_filter); } } else { MPQ_DVB_DBG_PRINT( "%s: NULL blocking filters added successfully\n", __func__); } return ret; }
static int mpq_tspp_remove_all_user_filters(int channel_id, enum tspp_source source) { struct tspp_filter tspp_filter; int ret = 0; int tsif = TSPP_GET_TSIF_NUM(channel_id); int i; MPQ_DVB_DBG_PRINT("%s: executed\n", __func__); for (i = 0; i < TSPP_MAX_HW_PID_FILTER_NUM; i++) { tspp_filter.priority = i; MPQ_DVB_DBG_PRINT("%s: Removing HW filter %d\n", __func__, tspp_filter.priority); if (tspp_remove_filter(0, channel_id, &tspp_filter)) ret = -1; mpq_tspp_release_hw_filter_index(tsif, i); mpq_dmx_tspp_info.tsif[tsif].filters[i].hw_index = -1; } return ret; }
static int mpq_tspp_remove_null_blocking_filters(int channel_id, enum tspp_source source) { struct tspp_filter tspp_filter; int tsif = TSPP_GET_TSIF_NUM(channel_id); int ret = 0; int i; MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n", __func__, channel_id, source); for (i = 0; i < TSPP_BLOCK_NULLS_FILTERS_NUM; i++) { tspp_filter.priority = i; if (tspp_remove_filter(0, channel_id, &tspp_filter)) { MPQ_DVB_ERR_PRINT("%s: failed to remove filter %d\n", __func__, i); ret = -1; } mpq_tspp_release_hw_filter_index(tsif, i); } return ret; }
/** * Removes filter from TSPP. * * @feed: The feed to remove * * Return error status * * The function checks if this is the only PID allocated within * the channel, if so, the channel is closed as well. */ static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed) { int tsif; int ret; int channel_id; atomic_t *data_cnt; int *channel_ref_count; struct tspp_filter tspp_filter; struct mpq_demux *mpq_demux = feed->demux->priv; /* determine the TSIF we are reading from */ if (mpq_demux->source == DMX_SOURCE_FRONT0) { tsif = 0; } else if (mpq_demux->source == DMX_SOURCE_FRONT1) { tsif = 1; } else { /* invalid source */ MPQ_DVB_ERR_PRINT( "%s: invalid input source (%d)\n", __func__, mpq_demux->source); return -EINVAL; } if (mutex_lock_interruptible(&mpq_dmx_tspp_info.tsif[tsif].mutex)) return -ERESTARTSYS; channel_id = TSPP_CHANNEL_ID(tsif, TSPP_CHANNEL); channel_ref_count = &mpq_dmx_tspp_info.tsif[tsif].channel_ref; data_cnt = &mpq_dmx_tspp_info.tsif[tsif].data_cnt; /* check if required TSPP pipe is already allocated or not */ if (*channel_ref_count == 0) { /* invalid feed provided as the channel is not allocated */ MPQ_DVB_ERR_PRINT( "%s: invalid feed (%d)\n", __func__, channel_id); ret = -EINVAL; goto remove_channel_failed; } tspp_filter.priority = mpq_tspp_get_filter_slot(tsif, feed->pid); if (tspp_filter.priority < 0) { /* invalid feed provided as it has no filter allocated */ MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_get_filter_slot failed (%d,%d)\n", __func__, feed->pid, tsif); ret = -EINVAL; goto remove_channel_failed; } mpq_dmx_tspp_info.tsif[tsif].filters[tspp_filter.priority].ref_count--; if (mpq_dmx_tspp_info.tsif[tsif]. filters[tspp_filter.priority].ref_count) { /* * there are still references to this pid, do not * remove the filter yet */ mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return 0; } ret = tspp_remove_filter(0, channel_id, &tspp_filter); if (ret < 0) { /* invalid feed provided as it has no filter allocated */ MPQ_DVB_ERR_PRINT( "%s: tspp_remove_filter failed (%d,%d)\n", __func__, channel_id, tspp_filter.priority); goto remove_channel_failed_restore_count; } mpq_dmx_tspp_info.tsif[tsif].filters[tspp_filter.priority].pid = -1; (*channel_ref_count)--; if (*channel_ref_count == 0) { /* channel is not used any more, release it */ tspp_unregister_notification(0, channel_id); tspp_close_channel(0, channel_id); tspp_close_stream(0, channel_id); atomic_set(data_cnt, 0); if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) mpq_dmx_channel_mem_free(tsif); } mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return 0; remove_channel_failed_restore_count: mpq_dmx_tspp_info.tsif[tsif].filters[tspp_filter.priority].ref_count++; remove_channel_failed: mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return ret; }
static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed) { int tsif; int ret; int channel_id; int slot; atomic_t *data_cnt; int *channel_ref_count; enum tspp_source tspp_source; struct tspp_filter tspp_filter; struct mpq_demux *mpq_demux = feed->demux->priv; int restore_null_blocking_filters = 0; int remove_accept_all_filter = 0; int remove_user_filters = 0; int accept_all_filter_existed = 0; MPQ_DVB_DBG_PRINT("%s: executed, PID = %d\n", __func__, feed->pid); if (mpq_demux->source == DMX_SOURCE_FRONT0) { tsif = 0; tspp_source = TSPP_SOURCE_TSIF0; } else if (mpq_demux->source == DMX_SOURCE_FRONT1) { tsif = 1; tspp_source = TSPP_SOURCE_TSIF1; } else { MPQ_DVB_ERR_PRINT( "%s: invalid input source (%d)\n", __func__, mpq_demux->source); return -EINVAL; } if (mutex_lock_interruptible(&mpq_dmx_tspp_info.tsif[tsif].mutex)) return -ERESTARTSYS; channel_id = TSPP_CHANNEL_ID(tsif, TSPP_CHANNEL); channel_ref_count = &mpq_dmx_tspp_info.tsif[tsif].channel_ref; data_cnt = &mpq_dmx_tspp_info.tsif[tsif].data_cnt; if (*channel_ref_count == 0) { MPQ_DVB_ERR_PRINT( "%s: invalid feed (%d)\n", __func__, channel_id); ret = -EINVAL; goto remove_channel_failed; } slot = mpq_tspp_get_filter_slot(tsif, feed->pid); if (slot < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_get_filter_slot failed (%d,%d)\n", __func__, feed->pid, tsif); ret = -EINVAL; goto remove_channel_failed; } mpq_dmx_tspp_info.tsif[tsif].filters[slot].ref_count--; if (mpq_dmx_tspp_info.tsif[tsif].filters[slot].ref_count) { mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return 0; } if (feed->pid == TSPP_PASS_THROUGH_PID) mpq_dmx_tspp_info.tsif[tsif].pass_all_flag = 0; else if (feed->pid == TSPP_NULL_PACKETS_PID) mpq_dmx_tspp_info.tsif[tsif].pass_nulls_flag = 0; mpq_dmx_tspp_info.tsif[tsif].filters[slot].pid = -1; if (mpq_dmx_tspp_info.tsif[tsif].current_filter_count <= TSPP_MAX_HW_PID_FILTER_NUM) { tspp_filter.priority = mpq_dmx_tspp_info.tsif[tsif].filters[slot].hw_index; ret = tspp_remove_filter(0, channel_id, &tspp_filter); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: tspp_remove_filter failed (%d,%d)\n", __func__, channel_id, tspp_filter.priority); goto remove_channel_failed_restore_count; } mpq_tspp_release_hw_filter_index(tsif, tspp_filter.priority); mpq_dmx_tspp_info.tsif[tsif].filters[slot].hw_index = -1; MPQ_DVB_DBG_PRINT( "%s: HW filtering mode: Removed TSPP HW filter, PID = %d, index = %d\n", __func__, feed->pid, tspp_filter.priority); } else if (mpq_dmx_tspp_info.tsif[tsif].current_filter_count == (TSPP_MAX_HW_PID_FILTER_NUM + 1)) { accept_all_filter_existed = mpq_dmx_tspp_info.tsif[tsif]. accept_all_filter_exists_flag; ret = mpq_tspp_add_accept_all_filter(channel_id, tspp_source); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_add_accept_all_filter(%d, %d) failed\n", __func__, channel_id, tspp_source); goto remove_channel_failed_restore_count; } ret = mpq_tspp_remove_null_blocking_filters(channel_id, tspp_source); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_remove_null_blocking_filters(%d, %d) failed\n", __func__, channel_id, tspp_source); restore_null_blocking_filters = 1; if (!accept_all_filter_existed) remove_accept_all_filter = 1; goto remove_channel_failed_restore_count; } ret = mpq_tspp_add_all_user_filters(channel_id, tspp_source); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_add_all_user_filters(%d, %d) failed\n", __func__, channel_id, tspp_source); remove_user_filters = 1; restore_null_blocking_filters = 1; if (!accept_all_filter_existed) remove_accept_all_filter = 1; goto remove_channel_failed_restore_count; } ret = mpq_tspp_remove_accept_all_filter(channel_id, tspp_source); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_remove_accept_all_filter(%d, %d) failed\n", __func__, channel_id, tspp_source); remove_user_filters = 1; restore_null_blocking_filters = 1; if (!accept_all_filter_existed) remove_accept_all_filter = 1; goto remove_channel_failed_restore_count; } } else { if ((mpq_dmx_tspp_info.tsif[tsif].pass_all_flag == 0) && (mpq_dmx_tspp_info.tsif[tsif].pass_nulls_flag == 0)) { ret = mpq_tspp_remove_accept_all_filter(channel_id, tspp_source); if (ret < 0) { MPQ_DVB_ERR_PRINT( "%s: mpq_tspp_remove_accept_all_filter(%d, %d) failed\n", __func__, channel_id, tspp_source); goto remove_channel_failed_restore_count; } } } mpq_dmx_tspp_info.tsif[tsif].current_filter_count--; (*channel_ref_count)--; MPQ_DVB_DBG_PRINT("%s: success, current_filter_count = %d\n", __func__, mpq_dmx_tspp_info.tsif[tsif].current_filter_count); if (*channel_ref_count == 0) { tspp_unregister_notification(0, channel_id); tspp_close_stream(0, channel_id); tspp_close_channel(0, channel_id); atomic_set(data_cnt, 0); if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) mpq_dmx_channel_mem_free(tsif); } mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return 0; remove_channel_failed_restore_count: mpq_dmx_tspp_info.tsif[tsif].filters[slot].pid = feed->pid; mpq_dmx_tspp_info.tsif[tsif].filters[slot].ref_count++; if (remove_user_filters) mpq_tspp_remove_all_user_filters(channel_id, tspp_source); if (restore_null_blocking_filters) mpq_tspp_add_null_blocking_filters(channel_id, tspp_source); if (remove_accept_all_filter) mpq_tspp_remove_accept_all_filter(channel_id, tspp_source); if (feed->pid == TSPP_PASS_THROUGH_PID) mpq_dmx_tspp_info.tsif[tsif].pass_all_flag = 1; else if (feed->pid == TSPP_NULL_PACKETS_PID) mpq_dmx_tspp_info.tsif[tsif].pass_nulls_flag = 1; remove_channel_failed: mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); return ret; }