/** * _rmnet_get_logical_ep() - Gets the logical end point configuration * structure for a network device * @dev: Device to get endpoint configuration from * @config_id: Logical endpoint id on device * Retrieves the logical_endpoint_config structure. * * Return: * - End point configuration structure * - NULL in case of an error */ struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep(struct net_device *dev, int config_id) { struct rmnet_phys_ep_conf_s *config; struct rmnet_logical_ep_conf_s *epconfig_l; if (rmnet_vnd_is_vnd(dev)) epconfig_l = rmnet_vnd_get_le_config(dev); else { config = _rmnet_get_phys_ep_config(dev); if (!config) return NULL; if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT) epconfig_l = &config->local_ep; else epconfig_l = &config->muxed_ep[config_id]; } return epconfig_l; }
/** * _rmnet_set_logical_endpoint_config() - Set logical endpoing config on device * @dev: Device to set endpoint configuration on * @config_id: logical endpoint id on device * @epconfig: endpoing configuration structure to set * * Return: * - RMNET_CONFIG_OK if successful * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range */ int _rmnet_set_logical_endpoint_config(struct net_device *dev, int config_id, struct rmnet_logical_ep_conf_s *epconfig) { struct rmnet_phys_ep_conf_s *config; struct rmnet_logical_ep_conf_s *epconfig_l; ASSERT_RTNL(); if (!dev) return RMNET_CONFIG_NO_SUCH_DEVICE; if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT || config_id >= RMNET_DATA_MAX_LOGICAL_EP) return RMNET_CONFIG_BAD_ARGUMENTS; if (rmnet_vnd_is_vnd(dev)) epconfig_l = rmnet_vnd_get_le_config(dev); else { config = _rmnet_get_phys_ep_config(dev); if (!config) return RMNET_CONFIG_UNKNOWN_ERROR; if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT) epconfig_l = &config->local_ep; else epconfig_l = &config->muxed_ep[config_id]; } memcpy(epconfig_l, epconfig, sizeof(struct rmnet_logical_ep_conf_s)); if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT) epconfig_l->mux_id = 0; else epconfig_l->mux_id = config_id; return RMNET_CONFIG_OK; }
/** * rmnet_force_unassociate_device() - Force a device to unassociate * @dev: Device to unassociate * * Return: * - void */ static void rmnet_force_unassociate_device(struct net_device *dev) { int i, j; struct net_device *vndev; struct rmnet_logical_ep_conf_s *cfg; struct rmnet_free_vnd_work *vnd_work; ASSERT_RTNL(); if (!dev) BUG(); if (!_rmnet_is_physical_endpoint_associated(dev)) { LOGM("%s", "Called on unassociated device, skipping"); return; } trace_rmnet_unregister_cb_clear_vnds(dev); vnd_work = (struct rmnet_free_vnd_work *) kmalloc(sizeof(struct rmnet_free_vnd_work), GFP_KERNEL); if (!vnd_work) { LOGH("%s", "Out of Memory"); return; } INIT_WORK(&vnd_work->work, _rmnet_free_vnd_later); vnd_work->count = 0; /* Check the VNDs for offending mappings */ for (i = 0, j = 0; i < RMNET_DATA_MAX_VND && j < RMNET_DATA_MAX_VND; i++) { vndev = rmnet_vnd_get_by_id(i); if (!vndev) { LOGL("VND %d not in use; skipping", i); continue; } cfg = rmnet_vnd_get_le_config(vndev); if (!cfg) { LOGH("Got NULL config from VND %d", i); BUG(); continue; } if (cfg->refcount && (cfg->egress_dev == dev)) { rmnet_unset_logical_endpoint_config(vndev, RMNET_LOCAL_LOGICAL_ENDPOINT); vnd_work->vnd_id[j] = i; j++; } } if (j > 0) { vnd_work->count = j; schedule_work(&vnd_work->work); } else { kfree(vnd_work); } /* Clear the mappings on the phys ep */ trace_rmnet_unregister_cb_clear_lepcs(dev); rmnet_unset_logical_endpoint_config(dev, RMNET_LOCAL_LOGICAL_ENDPOINT); for (i = 0; i < RMNET_DATA_MAX_LOGICAL_EP; i++) rmnet_unset_logical_endpoint_config(dev, i); rmnet_unassociate_network_device(dev); }