Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: gs_usb: add ethtool set_phys_id callback to locate physical device

This patch Implements the ethtool set_phys_id callback to ease the
locating of specific physical devices. Currently only supported on
candleLight interfaces.

Signed-off-by: Hubert Denkmair <hubert@denkmair.de>
Signed-off-by: Maximilian Schneider <max@schneidersoft.net>
[mkl: split codingstyle change sinto separate patch]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Maximilian Schneider and committed by
Marc Kleine-Budde
05ca5270 9be95c91

+85 -31
+85 -31
drivers/net/can/usb/gs_usb.c
··· 39 39 GS_USB_BREQ_MODE, 40 40 GS_USB_BREQ_BERR, 41 41 GS_USB_BREQ_BT_CONST, 42 - GS_USB_BREQ_DEVICE_CONFIG 42 + GS_USB_BREQ_DEVICE_CONFIG, 43 + GS_USB_BREQ_TIMESTAMP, 44 + GS_USB_BREQ_IDENTIFY, 43 45 }; 44 46 45 47 enum gs_can_mode { ··· 58 56 GS_CAN_STATE_BUS_OFF, 59 57 GS_CAN_STATE_STOPPED, 60 58 GS_CAN_STATE_SLEEPING 59 + }; 60 + 61 + enum gs_can_identify_mode { 62 + GS_CAN_IDENTIFY_OFF = 0, 63 + GS_CAN_IDENTIFY_ON 61 64 }; 62 65 63 66 /* data types passed between host and device */ ··· 108 101 u32 brp; 109 102 } __packed; 110 103 104 + struct gs_identify_mode { 105 + u32 mode; 106 + } __packed; 107 + 111 108 #define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) 112 109 #define GS_CAN_FEATURE_LOOP_BACK BIT(1) 113 110 #define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2) 114 111 #define GS_CAN_FEATURE_ONE_SHOT BIT(3) 112 + #define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4) 113 + #define GS_CAN_FEATURE_IDENTIFY BIT(5) 115 114 116 115 struct gs_device_bt_const { 117 116 u32 feature; ··· 737 724 .ndo_change_mtu = can_change_mtu, 738 725 }; 739 726 740 - static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface *intf) 727 + static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) 728 + { 729 + struct gs_can *dev = netdev_priv(netdev); 730 + struct gs_identify_mode imode; 731 + int rc; 732 + 733 + if (do_identify) 734 + imode.mode = GS_CAN_IDENTIFY_ON; 735 + else 736 + imode.mode = GS_CAN_IDENTIFY_OFF; 737 + 738 + rc = usb_control_msg(interface_to_usbdev(dev->iface), 739 + usb_sndctrlpipe(interface_to_usbdev(dev->iface), 740 + 0), 741 + GS_USB_BREQ_IDENTIFY, 742 + USB_DIR_OUT | USB_TYPE_VENDOR | 743 + USB_RECIP_INTERFACE, 744 + dev->channel, 745 + 0, 746 + &imode, 747 + sizeof(imode), 748 + 100); 749 + 750 + return (rc > 0) ? 0 : rc; 751 + } 752 + 753 + /* blink LED's for finding the this interface */ 754 + static int gs_usb_set_phys_id(struct net_device *dev, 755 + enum ethtool_phys_id_state state) 756 + { 757 + int rc = 0; 758 + 759 + switch (state) { 760 + case ETHTOOL_ID_ACTIVE: 761 + rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_ON); 762 + break; 763 + case ETHTOOL_ID_INACTIVE: 764 + rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_OFF); 765 + break; 766 + default: 767 + break; 768 + } 769 + 770 + return rc; 771 + } 772 + 773 + static const struct ethtool_ops gs_usb_ethtool_ops = { 774 + .set_phys_id = gs_usb_set_phys_id, 775 + }; 776 + 777 + static struct gs_can *gs_make_candev(unsigned int channel, 778 + struct usb_interface *intf, 779 + struct gs_device_config *dconf) 741 780 { 742 781 struct gs_can *dev; 743 782 struct net_device *netdev; ··· 877 812 if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) 878 813 dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; 879 814 880 - kfree(bt_const); 881 - 882 815 SET_NETDEV_DEV(netdev, &intf->dev); 816 + 817 + if (dconf->sw_version > 1) 818 + if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) 819 + netdev->ethtool_ops = &gs_usb_ethtool_ops; 820 + 821 + kfree(bt_const); 883 822 884 823 rc = register_candev(dev->netdev); 885 824 if (rc) { ··· 902 833 free_candev(dev->netdev); 903 834 } 904 835 905 - static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) 836 + static int gs_usb_probe(struct usb_interface *intf, 837 + const struct usb_device_id *id) 906 838 { 907 839 struct gs_usb *dev; 908 840 int rc = -ENOMEM; 909 841 unsigned int icount, i; 910 - struct gs_host_config *hconf; 911 - struct gs_device_config *dconf; 912 - 913 - hconf = kmalloc(sizeof(*hconf), GFP_KERNEL); 914 - if (!hconf) 915 - return -ENOMEM; 916 - 917 - hconf->byte_order = 0x0000beef; 842 + struct gs_host_config hconf = { 843 + .byte_order = 0x0000beef, 844 + }; 845 + struct gs_device_config dconf; 918 846 919 847 /* send host config */ 920 848 rc = usb_control_msg(interface_to_usbdev(intf), ··· 920 854 USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 921 855 1, 922 856 intf->altsetting[0].desc.bInterfaceNumber, 923 - hconf, 924 - sizeof(*hconf), 857 + &hconf, 858 + sizeof(hconf), 925 859 1000); 926 - 927 - kfree(hconf); 928 860 929 861 if (rc < 0) { 930 862 dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", 931 863 rc); 932 864 return rc; 933 865 } 934 - 935 - dconf = kmalloc(sizeof(*dconf), GFP_KERNEL); 936 - if (!dconf) 937 - return -ENOMEM; 938 866 939 867 /* read device config */ 940 868 rc = usb_control_msg(interface_to_usbdev(intf), ··· 937 877 USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 938 878 1, 939 879 intf->altsetting[0].desc.bInterfaceNumber, 940 - dconf, 941 - sizeof(*dconf), 880 + &dconf, 881 + sizeof(dconf), 942 882 1000); 943 883 if (rc < 0) { 944 884 dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n", 945 885 rc); 946 - 947 - kfree(dconf); 948 - 949 886 return rc; 950 887 } 951 888 952 - icount = dconf->icount+1; 953 - 954 - kfree(dconf); 955 - 889 + icount = dconf.icount + 1; 956 890 dev_info(&intf->dev, "Configuring for %d interfaces\n", icount); 957 891 958 892 if (icount > GS_MAX_INTF) { ··· 967 913 dev->udev = interface_to_usbdev(intf); 968 914 969 915 for (i = 0; i < icount; i++) { 970 - dev->canch[i] = gs_make_candev(i, intf); 916 + dev->canch[i] = gs_make_candev(i, intf, &dconf); 971 917 if (IS_ERR_OR_NULL(dev->canch[i])) { 972 918 /* save error code to return later */ 973 919 rc = PTR_ERR(dev->canch[i]);