diff options
Diffstat (limited to 'drivers/net/usb/cdc_mbim.c')
-rw-r--r-- | drivers/net/usb/cdc_mbim.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 80d27719ba38..bc23273d0455 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c | |||
@@ -107,15 +107,54 @@ static const struct net_device_ops cdc_mbim_netdev_ops = { | |||
107 | .ndo_vlan_rx_kill_vid = cdc_mbim_rx_kill_vid, | 107 | .ndo_vlan_rx_kill_vid = cdc_mbim_rx_kill_vid, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | /* Change the control interface altsetting and update the .driver_info | ||
111 | * pointer if the matching entry after changing class codes points to | ||
112 | * a different struct | ||
113 | */ | ||
114 | static int cdc_mbim_set_ctrlalt(struct usbnet *dev, struct usb_interface *intf, u8 alt) | ||
115 | { | ||
116 | struct usb_driver *driver = to_usb_driver(intf->dev.driver); | ||
117 | const struct usb_device_id *id; | ||
118 | struct driver_info *info; | ||
119 | int ret; | ||
120 | |||
121 | ret = usb_set_interface(dev->udev, | ||
122 | intf->cur_altsetting->desc.bInterfaceNumber, | ||
123 | alt); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | id = usb_match_id(intf, driver->id_table); | ||
128 | if (!id) | ||
129 | return -ENODEV; | ||
130 | |||
131 | info = (struct driver_info *)id->driver_info; | ||
132 | if (info != dev->driver_info) { | ||
133 | dev_dbg(&intf->dev, "driver_info updated to '%s'\n", | ||
134 | info->description); | ||
135 | dev->driver_info = info; | ||
136 | } | ||
137 | return 0; | ||
138 | } | ||
139 | |||
110 | static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) | 140 | static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) |
111 | { | 141 | { |
112 | struct cdc_ncm_ctx *ctx; | 142 | struct cdc_ncm_ctx *ctx; |
113 | struct usb_driver *subdriver = ERR_PTR(-ENODEV); | 143 | struct usb_driver *subdriver = ERR_PTR(-ENODEV); |
114 | int ret = -ENODEV; | 144 | int ret = -ENODEV; |
115 | u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf); | 145 | u8 data_altsetting = 1; |
116 | struct cdc_mbim_state *info = (void *)&dev->data; | 146 | struct cdc_mbim_state *info = (void *)&dev->data; |
117 | 147 | ||
118 | /* Probably NCM, defer for cdc_ncm_bind */ | 148 | /* should we change control altsetting on a NCM/MBIM function? */ |
149 | if (cdc_ncm_select_altsetting(intf) == CDC_NCM_COMM_ALTSETTING_MBIM) { | ||
150 | data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM; | ||
151 | ret = cdc_mbim_set_ctrlalt(dev, intf, CDC_NCM_COMM_ALTSETTING_MBIM); | ||
152 | if (ret) | ||
153 | goto err; | ||
154 | ret = -ENODEV; | ||
155 | } | ||
156 | |||
157 | /* we will hit this for NCM/MBIM functions if prefer_mbim is false */ | ||
119 | if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) | 158 | if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) |
120 | goto err; | 159 | goto err; |
121 | 160 | ||