static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet; struct usb_device *udev; struct rmnet_ctrl_dev *dev; udev = interface_to_usbdev(intf); device_set_wakeup_enable(&udev->dev, 0); unet = usb_get_intfdata(intf); if (!unet) { dev_err(&udev->dev, "%s:data device not found\n", __func__); return; } rmnet_usb_data_debugfs_cleanup(unet); dev = (struct rmnet_ctrl_dev *)unet->data[1]; if (!dev) { dev_err(&udev->dev, "%s:ctrl device not found\n", __func__); return; } #ifdef CONFIG_MDM_HSIC_PM unregister_udev_from_pm_dev(rmnet_pm_dev, udev); #endif unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(intf); }
static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet; struct rmnet_ctrl_dev *dev; unet = usb_get_intfdata(intf); if (!unet) { dev_err(&intf->dev, "%s:data device not found\n", __func__); return; } device_set_wakeup_enable(&unet->udev->dev, 0); rmnet_usb_data_debugfs_cleanup(unet); dev = (struct rmnet_ctrl_dev *)unet->data[1]; if (!dev) { dev_err(&intf->dev, "%s:ctrl device not found\n", __func__); return; } unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(intf); }
static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet; struct usb_device *udev; struct rmnet_ctrl_dev *dev; udev = interface_to_usbdev(intf); unet = usb_get_intfdata(intf); if (!unet) { dev_err(&udev->dev, "%s:data device not found\n", __func__); return; } dev = (struct rmnet_ctrl_dev *)unet->data[1]; if (!dev) { dev_err(&udev->dev, "%s:ctrl device not found\n", __func__); return; } unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(intf); }
static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet; struct rmnet_ctrl_dev *dev; unet = usb_get_intfdata(intf); if (!unet) { dev_err(&intf->dev, "%s:data device not found\n", __func__); return; } device_set_wakeup_enable(&unet->udev->dev, 0); rmnet_usb_data_debugfs_cleanup(unet); dev = (struct rmnet_ctrl_dev *)unet->data[1]; if (!dev) { dev_err(&intf->dev, "%s:ctrl device not found\n", __func__); return; } unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(intf); //++SSD_RIL:20120814: For CPU/Freq min default value if ( rnmet_usb_cpu_freq_enabled == 1 ) { rmnet_usb_freq_release(); } //--SSD_RIL }
void Gobinet_disconnect (struct usb_interface *pIntf) { struct usbnet * pDev; sGobiUSBNet * pGobiDev; if (pIntf == 0) { return -ENOMEM; } #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) pDev = usb_get_intfdata( pIntf ); #else pDev = (struct usbnet *)pIntf->dev.platform_data; #endif if (pDev == NULL || pDev->net == NULL) { DBG( "failed to get netdevice\n" ); return -ENXIO; } pGobiDev = (sGobiUSBNet *)pDev->data[0]; if (pGobiDev == NULL) { DBG( "failed to get QMIDevice\n" ); return -ENXIO; } #if 1 DeregisterQMIDevice(pGobiDev); #else cdev_del(&pGobiDev->mQMIDev.mCdev); #endif usbnet_disconnect(pIntf); }
static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet = usb_get_intfdata(intf); struct rmnet_ctrl_dev *dev; unsigned int n, rdev_cnt, unet_id; struct driver_info *info = unet->driver_info; bool mux = unet->data[4]; rdev_cnt = mux ? no_rmnet_insts_per_dev : 1; device_set_wakeup_enable(&unet->udev->dev, 0); for (n = 0; n < rdev_cnt; n++) { unet_id = n + info->data * no_rmnet_insts_per_dev; unet = mux ? unet_list[unet_id] : usb_get_intfdata(intf); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_ctrl_disconnect(dev); unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_data_debugfs_cleanup(unet); usb_set_intfdata(intf, unet); usbnet_disconnect(intf); unet_list[unet_id] = NULL; } }
static void cdc_ncm_disconnect(struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); if (dev == NULL) return; /* already disconnected */ usbnet_disconnect(intf); }
static void rmnet_usb_disconnect(struct usb_interface *intf) { struct usbnet *unet = usb_get_intfdata(intf); struct rmnet_ctrl_udev *dev; device_set_wakeup_enable(&unet->udev->dev, 0); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); dev = (struct rmnet_ctrl_udev *)unet->data[1]; rmnet_usb_ctrl_disconnect(dev); unet->data[0] = 0; unet->data[1] = 0; rmnet_usb_data_debugfs_cleanup(unet); usbnet_disconnect(intf); }
static int rmnet_usb_probe(struct usb_interface *iface, const struct usb_device_id *prod) { struct usbnet *unet; struct driver_info *info = (struct driver_info *)prod->driver_info; struct usb_device *udev; int status = 0; unsigned int i, unet_id, rdev_cnt, n = 0; bool mux; struct rmnet_ctrl_dev *dev; udev = interface_to_usbdev(iface); if (iface->num_altsetting != 1) { dev_err(&iface->dev, "%s invalid num_altsetting %u\n", __func__, iface->num_altsetting); status = -EINVAL; goto out; } mux = test_bit(info->data, &mux_enabled); rdev_cnt = mux ? no_rmnet_insts_per_dev : 1; info->in = 0; for (n = 0; n < rdev_cnt; n++) { /* Use this filed to increment device count this will be * used by bind to determin the forward link and reverse * link network interface names. */ info->in++; status = usbnet_probe(iface, prod); if (status < 0) { dev_err(&iface->dev, "usbnet_probe failed %d\n", status); goto out; } unet_id = n + info->data * no_rmnet_insts_per_dev; unet_list[unet_id] = unet = usb_get_intfdata(iface); /*store mux id for later access*/ unet->data[3] = n; /*save mux info for control and usbnet devices*/ unet->data[1] = unet->data[4] = mux; /*set rmnet operation mode to eth by default*/ set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]); /*update net device*/ rmnet_usb_setup(unet->net, mux); /*create /sys/class/net/rmnet_usbx/dbg_mask*/ status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask); if (status) { usbnet_disconnect(iface); goto out; } status = rmnet_usb_ctrl_probe(iface, unet->status, info->data, &unet->data[1]); if (status) { device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(iface); goto out; } status = rmnet_usb_data_debugfs_init(unet); if (status) dev_dbg(&iface->dev, "mode debugfs file is not available\n"); } usb_enable_autosuspend(udev); if (udev->parent && !udev->parent->parent) { /* allow modem and roothub to wake up suspended system */ device_set_wakeup_enable(&udev->dev, 1); device_set_wakeup_enable(&udev->parent->dev, 1); } return 0; out: for (i = 0; i < n; i++) { /* This cleanup happens only for MUX case */ unet_id = i + info->data * no_rmnet_insts_per_dev; unet = unet_list[unet_id]; dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_data_debugfs_cleanup(unet); rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usb_set_intfdata(iface, unet_list[unet_id]); usbnet_disconnect(iface); unet_list[unet_id] = NULL; } return status; }
/*=========================================================================== METHOD: GobiUSBNetProbe (Public Method) DESCRIPTION: Run usbnet_probe Setup QMI device PARAMETERS pIntf [ I ] - Pointer to interface pVIDPIDs [ I ] - Pointer to VID/PID table RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ int GobiUSBNetProbe( struct usb_interface * pIntf, const struct usb_device_id * pVIDPIDs ) { int is9x15 = 0; unsigned char ifacenum; int status; struct usbnet * pDev; sGobiUSBNet * pGobiDev; struct ethhdr *eth; #if 0 /* There exists a race condition in the firmware that sometimes results * in the absence of Ethernet framing of packets received from the device. * Therefore, a firmware work-around currently hard-codes the MAC address * to ensure valid Ethernet frames are sent to the host. We therefore * hard-code the network device MAC address to comply with the firmware */ const char default_addr[6] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}; #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) struct net_device_ops * pNetDevOps; #endif ifacenum = pIntf->cur_altsetting->desc.bInterfaceNumber; status = usbnet_probe( pIntf, pVIDPIDs ); if (status < 0) { DBG( "usbnet_probe failed %d\n", status ); return status; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,19 )) pIntf->needs_remote_wakeup = 1; #endif #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) pDev = usb_get_intfdata( pIntf ); #else pDev = (struct usbnet *)pIntf->dev.platform_data; #endif if (pDev == NULL || pDev->net == NULL) { DBG( "failed to get netdevice\n" ); usbnet_disconnect( pIntf ); return -ENXIO; } pGobiDev = kmalloc( sizeof( sGobiUSBNet ), GFP_KERNEL ); if (pGobiDev == NULL) { DBG( "falied to allocate device buffers" ); usbnet_disconnect( pIntf ); return -ENOMEM; } pDev->data[0] = (unsigned long)pGobiDev; pGobiDev->mpNetDev = pDev; #ifdef DATA_MODE_RP pDev->net->flags |= IFF_NOARP; DBG( "RawIP mode\n" ); #endif // Clearing endpoint halt is a magic handshake that brings // the device out of low power (airplane) mode // NOTE: FCC verification should be done before this, if required usb_clear_halt( pGobiDev->mpNetDev->udev, pDev->out ); // Overload PM related network functions #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pGobiDev->mpUSBNetOpen = pDev->net->open; pDev->net->open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pDev->net->stop; pDev->net->stop = GobiUSBNetStop; pDev->net->hard_start_xmit = GobiUSBNetStartXmit; pDev->net->tx_timeout = GobiUSBNetTXTimeout; #else pNetDevOps = kmalloc( sizeof( struct net_device_ops ), GFP_KERNEL ); if (pNetDevOps == NULL) { DBG( "falied to allocate net device ops" ); usbnet_disconnect( pIntf ); return -ENOMEM; } memcpy( pNetDevOps, pDev->net->netdev_ops, sizeof( struct net_device_ops ) ); pGobiDev->mpUSBNetOpen = pNetDevOps->ndo_open; pNetDevOps->ndo_open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pNetDevOps->ndo_stop; pNetDevOps->ndo_stop = GobiUSBNetStop; #ifdef CONFIG_PM pNetDevOps->ndo_start_xmit = GobiUSBNetStartXmit; pNetDevOps->ndo_tx_timeout = GobiUSBNetTXTimeout; #else pNetDevOps->ndo_start_xmit = usbnet_start_xmit; pNetDevOps->ndo_tx_timeout = usbnet_tx_timeout; #endif /* CONFIG_PM */ pDev->net->netdev_ops = pNetDevOps; #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) memset( &(pGobiDev->mpNetDev->stats), 0, sizeof( struct net_device_stats ) ); #else memset( &(pGobiDev->mpNetDev->net->stats), 0, sizeof( struct net_device_stats ) ); #endif pGobiDev->mpIntf = pIntf; memset( &(pGobiDev->mMEID), '0', 14 ); /* change MAC addr to include, ifacenum, and to be unique */ pGobiDev->mpNetDev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); pGobiDev->mpNetDev->net->dev_addr[ETH_ALEN-1] = ifacenum; DBG( "Mac Address:\n" ); PrintHex( &pGobiDev->mpNetDev->net->dev_addr[0], 6 ); #if 0 /* interfers with multiple interface support and no longer appears to be necessary */ /* Hard-code the host MAC address to comply with the firmware workaround */ memcpy(&pGobiDev->mpNetDev->net->dev_addr[0], &default_addr[0], 6); DBG( "Default Mac Address:\n" ); PrintHex( &pGobiDev->mpNetDev->net->dev_addr[0], 6 ); #endif /* Create ethernet header for IPv4 packets */ eth = (struct ethhdr *)pGobiDev->eth_hdr_tmpl_ipv4; memcpy(ð->h_dest, &pGobiDev->mpNetDev->net->dev_addr[0], ETH_ALEN); memcpy(ð->h_source, &pGobiDev->mpNetDev->net->dev_addr[0], ETH_ALEN); eth->h_proto = cpu_to_be16(ETH_P_IP); /* Create ethernet header for IPv6 packets */ eth = (struct ethhdr *)pGobiDev->eth_hdr_tmpl_ipv6; memcpy(ð->h_dest, &pGobiDev->mpNetDev->net->dev_addr[0], ETH_ALEN); memcpy(ð->h_source, &pGobiDev->mpNetDev->net->dev_addr[0], ETH_ALEN); eth->h_proto = cpu_to_be16(ETH_P_IPV6); pGobiDev->mbQMIValid = false; memset( &pGobiDev->mQMIDev, 0, sizeof( sQMIDev ) ); pGobiDev->mQMIDev.mbCdevIsInitialized = false; pGobiDev->mQMIDev.mpDevClass = gpClass; #ifdef CONFIG_PM init_completion( &pGobiDev->mAutoPM.mThreadDoWork ); #endif /* CONFIG_PM */ spin_lock_init( &pGobiDev->mQMIDev.mClientMemLock ); // Default to device down pGobiDev->mDownReason = 0; GobiSetDownReason( pGobiDev, NO_NDIS_CONNECTION ); GobiSetDownReason( pGobiDev, NET_IFACE_STOPPED ); // Register QMI if (pDev->driver_info->data && test_bit(BIT_9X15, &pDev->driver_info->data)) { is9x15 = 1; } status = RegisterQMIDevice( pGobiDev, is9x15 ); if (status != 0) { // usbnet_disconnect() will call GobiNetDriverUnbind() which will call // DeregisterQMIDevice() to clean up any partially created QMI device usbnet_disconnect( pIntf ); return status; } // Success return 0; }
static int rmnet_usb_probe(struct usb_interface *iface, const struct usb_device_id *prod) { struct usbnet *unet; struct driver_info *info = (struct driver_info *)prod->driver_info; struct usb_device *udev; int status = 0; unsigned int i, unet_id, rdev_cnt, n = 0; bool mux; struct rmnet_ctrl_dev *dev; udev = interface_to_usbdev(iface); if (iface->num_altsetting != 1) { dev_err(&iface->dev, "%s invalid num_altsetting %u\n", __func__, iface->num_altsetting); status = -EINVAL; goto out; } mux = test_bit(info->data, &mux_enabled); rdev_cnt = mux ? no_rmnet_insts_per_dev : 1; info->in = 0; for (n = 0; n < rdev_cnt; n++) { /* */ info->in++; status = usbnet_probe(iface, prod); if (status < 0) { dev_err(&iface->dev, "usbnet_probe failed %d\n", status); goto out; } unet_id = n + info->data * no_rmnet_insts_per_dev; unet_list[unet_id] = unet = usb_get_intfdata(iface); /* */ unet->data[3] = n; /* */ unet->data[1] = unet->data[4] = mux; /* */ set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]); /* */ rmnet_usb_setup(unet->net, mux); /* */ status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask); if (status) { usbnet_disconnect(iface); goto out; } status = rmnet_usb_ctrl_probe(iface, unet->status, info->data, &unet->data[1]); if (status) { device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(iface); goto out; } status = rmnet_usb_data_debugfs_init(unet); if (status) dev_dbg(&iface->dev, "mode debugfs file is not available\n"); } usb_enable_autosuspend(udev); if (udev->parent && !udev->parent->parent) { /* */ device_set_wakeup_enable(&udev->dev, 1); device_set_wakeup_enable(&udev->parent->dev, 1); } return 0; out: for (i = 0; i < n; i++) { /* */ unet_id = i + info->data * no_rmnet_insts_per_dev; unet = unet_list[unet_id]; dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_data_debugfs_cleanup(unet); rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usb_set_intfdata(iface, unet_list[unet_id]); usbnet_disconnect(iface); unet_list[unet_id] = NULL; } return status; }
/*=========================================================================== METHOD: GobiUSBNetProbe (Public Method) DESCRIPTION: Run usbnet_probe Setup QMI device PARAMETERS pIntf [ I ] - Pointer to interface pVIDPIDs [ I ] - Pointer to VID/PID table RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ int GobiUSBNetProbe( struct usb_interface * pIntf, const struct usb_device_id * pVIDPIDs ) { int status; struct usbnet * pDev; sGobiUSBNet * pGobiDev; sEndpoints * pEndpoints; int pipe; unsigned char my_mac_addr[ETH_ALEN]; struct sockaddr addr; #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) struct net_device_ops * pNetDevOps; #endif pEndpoints = GatherEndpoints( pIntf ); if (pEndpoints == NULL) { return -ENODEV; } status = usbnet_probe( pIntf, pVIDPIDs ); if (status < 0) { DBG( "usbnet_probe failed %d\n", status ); return status; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,19 )) pIntf->needs_remote_wakeup = 1; #endif #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) pDev = usb_get_intfdata( pIntf ); #else pDev = (struct usbnet *)pIntf->dev.platform_data; #endif if (pDev == NULL || pDev->net == NULL) { DBG( "failed to get netdevice\n" ); usbnet_disconnect( pIntf ); kfree( pEndpoints ); return -ENXIO; } //modify Mac from param arthur 20140122 if(mac_addr != NULL){ str2mac(mac_addr,my_mac_addr); addr.sa_family = 1; memset(addr.sa_data,0,ETH_ALEN); memcpy(addr.sa_data, my_mac_addr, ETH_ALEN); #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pDev->net->set_mac_address(pDev->net,&addr); #else pDev->net->netdev_ops->ndo_set_mac_address(pDev->net,&addr); #endif } //check the first 4 bits of MAC addr , for they can't be 4 or 6 arthur 20140122 if(((pDev->net->dev_addr[0] & 0xf0) == 0x40) || ((pDev->net->dev_addr[0] & 0xf0) == 0x60)) { printk("Need to Modify Mac\n" ); addr.sa_family = 1; memset(addr.sa_data,0,ETH_ALEN); memcpy(addr.sa_data, pDev->net->dev_addr, ETH_ALEN); addr.sa_data[0] |= 0x10; #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pDev->net->set_mac_address(pDev->net,&addr); #else pDev->net->netdev_ops->ndo_set_mac_address(pDev->net,&addr); #endif } pGobiDev = kmalloc( sizeof( sGobiUSBNet ), GFP_KERNEL ); if (pGobiDev == NULL) { DBG( "falied to allocate device buffers" ); usbnet_disconnect( pIntf ); kfree( pEndpoints ); return -ENOMEM; } pDev->data[0] = (unsigned long)pGobiDev; pGobiDev->mpNetDev = pDev; pGobiDev->mpEndpoints = pEndpoints; // Clearing endpoint halt is a magic handshake that brings // the device out of low power (airplane) mode // NOTE: FCC verification should be done before this, if required pipe = usb_sndbulkpipe( pGobiDev->mpNetDev->udev, pGobiDev->mpEndpoints->mBlkOutEndp ); usb_clear_halt( pGobiDev->mpNetDev->udev, pipe ); // Overload PM related network functions #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pGobiDev->mpUSBNetOpen = pDev->net->open; pDev->net->open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pDev->net->stop; pDev->net->stop = GobiUSBNetStop; // pDev->net->hard_start_xmit = GobiUSBNetStartXmit; // pDev->net->tx_timeout = GobiUSBNetTXTimeout; #else pNetDevOps = kmalloc( sizeof( struct net_device_ops ), GFP_KERNEL ); if (pNetDevOps == NULL) { DBG( "falied to allocate net device ops" ); usbnet_disconnect( pIntf ); return -ENOMEM; } memcpy( pNetDevOps, pDev->net->netdev_ops, sizeof( struct net_device_ops ) ); pGobiDev->mpUSBNetOpen = pNetDevOps->ndo_open; pNetDevOps->ndo_open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pNetDevOps->ndo_stop; pNetDevOps->ndo_stop = GobiUSBNetStop; // pNetDevOps->ndo_start_xmit = GobiUSBNetStartXmit; // pNetDevOps->ndo_tx_timeout = GobiUSBNetTXTimeout; pDev->net->netdev_ops = pNetDevOps; #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) memset( &(pGobiDev->mpNetDev->stats), 0, sizeof( struct net_device_stats ) ); #else memset( &(pGobiDev->mpNetDev->net->stats), 0, sizeof( struct net_device_stats ) ); #endif pGobiDev->mpIntf = pIntf; memset( &(pGobiDev->mMEID), '0', 14 ); DBG( "Mac Address:\n" ); PrintHex( &pGobiDev->mpNetDev->net->dev_addr[0], 6 ); pGobiDev->mbQMIValid = false; memset( &pGobiDev->mQMIDev, 0, sizeof( sQMIDev ) ); pGobiDev->mQMIDev.mbCdevIsInitialized = false; pGobiDev->mQMIDev.mpDevClass = gpClass; init_completion( &pGobiDev->mAutoPM.mThreadDoWork ); spin_lock_init( &pGobiDev->mQMIDev.mClientMemLock ); // Default to device down pGobiDev->mDownReason = 0; GobiSetDownReason( pGobiDev, NO_NDIS_CONNECTION ); GobiSetDownReason( pGobiDev, NET_IFACE_STOPPED ); // Register QMI status = RegisterQMIDevice( pGobiDev ); if (status != 0) { // usbnet_disconnect() will call GobiNetDriverUnbind() which will call // DeregisterQMIDevice() to clean up any partially created QMI device usbnet_disconnect( pIntf ); return status; } // Success return 0; }
static int rmnet_usb_probe(struct usb_interface *iface, const struct usb_device_id *prod) { struct usbnet *unet; struct driver_info *info; struct usb_device *udev; unsigned int iface_num; static int first_rmnet_iface_num = -EINVAL; int status = 0; //++SSD_RIL:20120731: For tx/rx enable_hlt/disable_hlt if( machine_is_evitareul() ) { rnmet_usb_hlt_enabled = 1; pr_info("%s:rnmet_usb_hlt_enabled = 1\n", __func__); } //--SSD_RIL //++SSD_RIL:20120814: For CPU/Freq min default value if ( rnmet_usb_hlt_enabled == 1 && get_radio_flag() & 0x0002 ) { rnmet_usb_cpu_freq_enabled = 1; } //--SSD_RIL iface_num = iface->cur_altsetting->desc.bInterfaceNumber; if (iface->num_altsetting != 1) { dev_err(&iface->dev, "%s invalid num_altsetting %u\n", __func__, iface->num_altsetting); status = -EINVAL; goto out; } info = (struct driver_info *)prod->driver_info; if (!test_bit(iface_num, &info->data)) return -ENODEV; status = usbnet_probe(iface, prod); if (status < 0) { dev_err(&iface->dev, "usbnet_probe failed %d\n", status); goto out; } unet = usb_get_intfdata(iface); /*set rmnet operation mode to eth by default*/ set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]); /*update net device*/ rmnet_usb_setup(unet->net); /*create /sys/class/net/rmnet_usbx/dbg_mask*/ status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask); if (status) goto out; if (first_rmnet_iface_num == -EINVAL) first_rmnet_iface_num = iface_num; /*save control device intstance */ unet->data[1] = (unsigned long)ctrl_dev \ [iface_num - first_rmnet_iface_num]; status = rmnet_usb_ctrl_probe(iface, unet->status, (struct rmnet_ctrl_dev *)unet->data[1]); if (status) goto out; status = rmnet_usb_data_debugfs_init(unet); if (status) dev_dbg(&iface->dev, "mode debugfs file is not available\n"); udev = unet->udev; if (udev->parent && !udev->parent->parent) { /* allow modem and roothub to wake up suspended system */ device_set_wakeup_enable(&udev->dev, 1); device_set_wakeup_enable(&udev->parent->dev, 1); /* set default autosuspend timeout for modem and roothub */ pm_runtime_set_autosuspend_delay(&udev->dev, 1000); dev_err(&udev->dev, "pm_runtime_set_autosuspend_delay 1000\n"); pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200); dev_err(&udev->parent->dev, "pm_runtime_set_autosuspend_delay 200\n"); } out: //++SSD_RIL:20120814: For CPU/Freq min default value if ( rnmet_usb_cpu_freq_enabled == 1 ) { rmnet_usb_freq_request(); } //--SSD_RIL //++SSD_RIL:20121017: get -71 but already register rmnet netdev if (status == -EPROTO && already_register_rmNET ) { pr_info("%s fail ,status = %d,unregister_netdev \n", __func__,status); //unregister_netdev(unet->net); //usb_put_dev(unet->udev); usbnet_disconnect(iface); } //--SSD_RIL:20121017: get -71 but already register rmnet netdev return status; }
/*=========================================================================== METHOD: QCUSBNetProbe (Public Method) DESCRIPTION: Run usbnet_probe Setup QMI device PARAMETERS pIntf [ I ] - Pointer to interface pVIDPIDs [ I ] - Pointer to VID/PID table RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ int QCUSBNetProbe( struct usb_interface * pIntf, const struct usb_device_id * pVIDPIDs ) { int status; struct usbnet * pDev; sQCUSBNet * pQCDev; #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) struct net_device_ops * pNetDevOps; #endif int i; u8 *addr; status = usbnet_probe( pIntf, pVIDPIDs ); if(status < 0 ) { DBG( "usbnet_probe failed %d\n", status ); return status; } #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) pDev = usb_get_intfdata( pIntf ); #else pDev = (struct usbnet *)pIntf->dev.platform_data; #endif if (pDev == NULL || pDev->net == NULL) { DBG( "failed to get netdevice\n" ); usbnet_disconnect( pIntf ); return -ENXIO; } pQCDev = kmalloc( sizeof( sQCUSBNet ), GFP_KERNEL ); if (pQCDev == NULL) { DBG( "falied to allocate device buffers" ); usbnet_disconnect( pIntf ); return -ENOMEM; } pDev->data[0] = (unsigned long)pQCDev; pQCDev->mpNetDev = pDev; // Overload PM related network functions #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pQCDev->mpUSBNetOpen = pDev->net->open; pDev->net->open = QCUSBNetOpen; pQCDev->mpUSBNetStop = pDev->net->stop; pDev->net->stop = QCUSBNetStop; pDev->net->hard_start_xmit = QCUSBNetStartXmit; pDev->net->tx_timeout = QCUSBNetTXTimeout; #else pNetDevOps = kmalloc( sizeof( struct net_device_ops ), GFP_KERNEL ); if (pNetDevOps == NULL) { DBG( "falied to allocate net device ops" ); usbnet_disconnect( pIntf ); return -ENOMEM; } memcpy( pNetDevOps, pDev->net->netdev_ops, sizeof( struct net_device_ops ) ); pQCDev->mpUSBNetOpen = pNetDevOps->ndo_open; pNetDevOps->ndo_open = QCUSBNetOpen; pQCDev->mpUSBNetStop = pNetDevOps->ndo_stop; pNetDevOps->ndo_stop = QCUSBNetStop; pNetDevOps->ndo_start_xmit = QCUSBNetStartXmit; pNetDevOps->ndo_tx_timeout = QCUSBNetTXTimeout; pDev->net->netdev_ops = pNetDevOps; #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) memset( &(pQCDev->mpNetDev->stats), 0, sizeof( struct net_device_stats ) ); #else memset( &(pQCDev->mpNetDev->net->stats), 0, sizeof( struct net_device_stats ) ); #endif pQCDev->mpIntf = pIntf; memset( &(pQCDev->mMEID), '0', 14 ); pQCDev->mbQMIValid = false; memset( &pQCDev->mQMIDev, 0, sizeof( sQMIDev ) ); pQCDev->mQMIDev.mbCdevIsInitialized = false; pQCDev->mQMIDev.mpDevClass = gpClass; init_completion( &pQCDev->mAutoPM.mThreadDoWork ); spin_lock_init( &pQCDev->mQMIDev.mClientMemLock ); // Default to device down pQCDev->mDownReason = 0; QSetDownReason( pQCDev, NO_NDIS_CONNECTION ); QSetDownReason( pQCDev, NET_IFACE_STOPPED ); // Register QMI status = RegisterQMIDevice( pQCDev ); if (status != 0) { // usbnet_disconnect() will call QCUSBNetUnbind() which will call // DeregisterQMIDevice() to clean up any partially created QMI device usbnet_disconnect( pIntf ); return status; } // After calling RegisterQMIDevice mMEID is valid. Although most // drivers set the MAC address in bind(), we need to wait until the // MEID is available. addr = &pDev->net->dev_addr[0]; for (i = 0; i < 6; i++) addr[i] = (nibble(pQCDev->mMEID[i*2+2]) << 4) + nibble(pQCDev->mMEID[i*2+3]); addr [0] &= 0xfe; /* clear multicast bit */ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ DBG( "Mac Address:\n" ); PrintHex( &pQCDev->mpNetDev->net->dev_addr[0], 6 ); // Success return 0; }
static int rmnet_usb_probe(struct usb_interface *iface, const struct usb_device_id *prod) { struct usbnet *unet; struct driver_info *info = (struct driver_info *)prod->driver_info; struct usb_device *udev; int status = 0; unsigned int i, unet_id, rdev_cnt, n = 0; bool mux; struct rmnet_ctrl_dev *dev; udev = interface_to_usbdev(iface); if (iface->num_altsetting != 1) { dev_err(&iface->dev, "%s invalid num_altsetting %u\n", __func__, iface->num_altsetting); status = -EINVAL; goto out; } mux = test_bit(info->data, &mux_enabled); if (prod->idProduct == 0x908a) mux = true; else mux = false; mux_enabled_per_pid = mux; rdev_cnt = mux ? no_rmnet_insts_per_dev : 1; info->in = 0; for (n = 0; n < rdev_cnt; n++) { info->in++; status = usbnet_probe(iface, prod); if (status < 0) { dev_err(&iface->dev, "usbnet_probe failed %d\n", status); goto out; } unet_id = n + info->data * no_rmnet_insts_per_dev; unet_list[unet_id] = unet = usb_get_intfdata(iface); unet->data[3] = n; unet->data[1] = unet->data[4] = mux; set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]); rmnet_usb_setup(unet->net, mux); status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask); if (status) { usbnet_disconnect(iface); goto out; } status = rmnet_usb_ctrl_probe(iface, unet->status, info->data, &unet->data[1]); if (status) { device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(iface); goto out; } status = rmnet_usb_data_debugfs_init(unet); if (status) dev_dbg(&iface->dev, "mode debugfs file is not available\n"); } if (udev->parent && !udev->parent->parent) { device_set_wakeup_enable(&udev->dev, 1); device_set_wakeup_enable(&udev->parent->dev, 1); pm_runtime_set_autosuspend_delay(&udev->dev, 1000); pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200); #if defined(CONFIG_MONITOR_STREAMING_PORT_SOCKET) && defined(CONFIG_MSM_NONSMD_PACKET_FILTER) original_autosuspend_timer = udev->dev.power.autosuspend_delay; dev_info(&udev->dev, "original_autosuspend_timer:%d\n", original_autosuspend_timer); #endif } return 0; out: for (i = 0; i < n; i++) { unet_id = i + info->data * no_rmnet_insts_per_dev; unet = unet_list[unet_id]; dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_data_debugfs_cleanup(unet); rmnet_usb_ctrl_disconnect(dev); device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usb_set_intfdata(iface, unet_list[unet_id]); usbnet_disconnect(iface); unet_list[unet_id] = NULL; } return status; }
/*=========================================================================== METHOD: GobiUSBNetProbe (Public Method) DESCRIPTION: Run usbnet_probe Setup QMI device PARAMETERS pIntf [ I ] - Pointer to interface pVIDPIDs [ I ] - Pointer to VID/PID table RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ int GobiUSBNetProbe( struct usb_interface * pIntf, const struct usb_device_id * pVIDPIDs ) { int status; struct usbnet * pDev; sGobiUSBNet * pGobiDev; #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) struct net_device_ops * pNetDevOps; #endif status = usbnet_probe( pIntf, pVIDPIDs ); if(status < 0 ) { DBG( "usbnet_probe failed %d\n", status ); return status; } #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) pDev = usb_get_intfdata( pIntf ); #else pDev = (struct usbnet *)pIntf->dev.platform_data; #endif if (pDev == NULL || pDev->net == NULL) { DBG( "failed to get netdevice\n" ); usbnet_disconnect( pIntf ); return -ENXIO; } pGobiDev = kmalloc( sizeof( sGobiUSBNet ), GFP_KERNEL ); if (pGobiDev == NULL) { DBG( "falied to allocate device buffers" ); usbnet_disconnect( pIntf ); return -ENOMEM; } pDev->data[0] = (unsigned long)pGobiDev; pGobiDev->mpNetDev = pDev; // Overload PM related network functions #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) pGobiDev->mpUSBNetOpen = pDev->net->open; pDev->net->open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pDev->net->stop; pDev->net->stop = GobiUSBNetStop; pDev->net->hard_start_xmit = GobiUSBNetStartXmit; pDev->net->tx_timeout = GobiUSBNetTXTimeout; #else pNetDevOps = kmalloc( sizeof( struct net_device_ops ), GFP_KERNEL ); if (pNetDevOps == NULL) { DBG( "falied to allocate net device ops" ); usbnet_disconnect( pIntf ); return -ENOMEM; } memcpy( pNetDevOps, pDev->net->netdev_ops, sizeof( struct net_device_ops ) ); pGobiDev->mpUSBNetOpen = pNetDevOps->ndo_open; pNetDevOps->ndo_open = GobiUSBNetOpen; pGobiDev->mpUSBNetStop = pNetDevOps->ndo_stop; pNetDevOps->ndo_stop = GobiUSBNetStop; pNetDevOps->ndo_start_xmit = GobiUSBNetStartXmit; pNetDevOps->ndo_tx_timeout = GobiUSBNetTXTimeout; pDev->net->netdev_ops = pNetDevOps; #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) memset( &(pGobiDev->mpNetDev->stats), 0, sizeof( struct net_device_stats ) ); #else memset( &(pGobiDev->mpNetDev->net->stats), 0, sizeof( struct net_device_stats ) ); #endif pGobiDev->mpIntf = pIntf; memset( &(pGobiDev->mMEID), '0', 14 ); DBG( "Mac Address:\n" ); PrintHex( &pGobiDev->mpNetDev->net->dev_addr[0], 6 ); pGobiDev->mbQMIValid = false; memset( &pGobiDev->mQMIDev, 0, sizeof( sQMIDev ) ); pGobiDev->mQMIDev.mbCdevIsInitialized = false; pGobiDev->mQMIDev.mpDevClass = gpClass; init_completion( &pGobiDev->mAutoPM.mThreadDoWork ); spin_lock_init( &pGobiDev->mQMIDev.mClientMemLock ); // Default to device down pGobiDev->mDownReason = 0; GobiSetDownReason( pGobiDev, NO_NDIS_CONNECTION ); GobiSetDownReason( pGobiDev, NET_IFACE_STOPPED ); // Register QMI status = RegisterQMIDevice( pGobiDev ); if (status != 0) { // usbnet_disconnect() will call GobiNetDriverUnbind() which will call // DeregisterQMIDevice() to clean up any partially created QMI device usbnet_disconnect( pIntf ); return status; } // Success return 0; }
static int rmnet_usb_probe(struct usb_interface *iface, const struct usb_device_id *prod) { struct usbnet *unet; struct driver_info *info = (struct driver_info *)prod->driver_info; struct usb_device *udev; int status = 0; udev = interface_to_usbdev(iface); if (iface->num_altsetting != 1) { dev_err(&iface->dev, "%s invalid num_altsetting %u\n", __func__, iface->num_altsetting); return -EINVAL; } status = usbnet_probe(iface, prod); if (status < 0) { dev_err(&iface->dev, "usbnet_probe failed %d\n", status); return status; } unet = usb_get_intfdata(iface); /*set rmnet operation mode to eth by default*/ set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]); /*update net device*/ rmnet_usb_setup(unet->net); /*create /sys/class/net/rmnet_usbx/dbg_mask*/ status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask); if (status) { usbnet_disconnect(iface); return status; } status = rmnet_usb_ctrl_probe(iface, unet->status, info->data, &unet->data[1]); if (status) { device_remove_file(&unet->net->dev, &dev_attr_dbg_mask); usbnet_disconnect(iface); return status; } status = rmnet_usb_data_debugfs_init(unet); if (status) dev_dbg(&iface->dev, "mode debugfs file is not available\n"); usb_enable_autosuspend(udev); if (udev->parent && !udev->parent->parent) { /* allow modem and roothub to wake up suspended system */ device_set_wakeup_enable(&udev->dev, 1); device_set_wakeup_enable(&udev->parent->dev, 1); } return 0; }