1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * usb.c - Hardware dependent module for USB
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/fs.h>
10*4882a593Smuzhiyun #include <linux/usb.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/cdev.h>
14*4882a593Smuzhiyun #include <linux/device.h>
15*4882a593Smuzhiyun #include <linux/list.h>
16*4882a593Smuzhiyun #include <linux/completion.h>
17*4882a593Smuzhiyun #include <linux/mutex.h>
18*4882a593Smuzhiyun #include <linux/spinlock.h>
19*4882a593Smuzhiyun #include <linux/interrupt.h>
20*4882a593Smuzhiyun #include <linux/workqueue.h>
21*4882a593Smuzhiyun #include <linux/sysfs.h>
22*4882a593Smuzhiyun #include <linux/dma-mapping.h>
23*4882a593Smuzhiyun #include <linux/etherdevice.h>
24*4882a593Smuzhiyun #include <linux/uaccess.h>
25*4882a593Smuzhiyun #include <linux/most.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define USB_MTU 512
28*4882a593Smuzhiyun #define NO_ISOCHRONOUS_URB 0
29*4882a593Smuzhiyun #define AV_PACKETS_PER_XACT 2
30*4882a593Smuzhiyun #define BUF_CHAIN_SIZE 0xFFFF
31*4882a593Smuzhiyun #define MAX_NUM_ENDPOINTS 30
32*4882a593Smuzhiyun #define MAX_SUFFIX_LEN 10
33*4882a593Smuzhiyun #define MAX_STRING_LEN 80
34*4882a593Smuzhiyun #define MAX_BUF_SIZE 0xFFFF
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */
37*4882a593Smuzhiyun #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */
38*4882a593Smuzhiyun #define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */
39*4882a593Smuzhiyun #define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */
40*4882a593Smuzhiyun #define USB_DEV_ID_OS81210 0xCF30 /* PID: USB OS81210 */
41*4882a593Smuzhiyun /* DRCI Addresses */
42*4882a593Smuzhiyun #define DRCI_REG_NI_STATE 0x0100
43*4882a593Smuzhiyun #define DRCI_REG_PACKET_BW 0x0101
44*4882a593Smuzhiyun #define DRCI_REG_NODE_ADDR 0x0102
45*4882a593Smuzhiyun #define DRCI_REG_NODE_POS 0x0103
46*4882a593Smuzhiyun #define DRCI_REG_MEP_FILTER 0x0140
47*4882a593Smuzhiyun #define DRCI_REG_HASH_TBL0 0x0141
48*4882a593Smuzhiyun #define DRCI_REG_HASH_TBL1 0x0142
49*4882a593Smuzhiyun #define DRCI_REG_HASH_TBL2 0x0143
50*4882a593Smuzhiyun #define DRCI_REG_HASH_TBL3 0x0144
51*4882a593Smuzhiyun #define DRCI_REG_HW_ADDR_HI 0x0145
52*4882a593Smuzhiyun #define DRCI_REG_HW_ADDR_MI 0x0146
53*4882a593Smuzhiyun #define DRCI_REG_HW_ADDR_LO 0x0147
54*4882a593Smuzhiyun #define DRCI_REG_BASE 0x1100
55*4882a593Smuzhiyun #define DRCI_COMMAND 0x02
56*4882a593Smuzhiyun #define DRCI_READ_REQ 0xA0
57*4882a593Smuzhiyun #define DRCI_WRITE_REQ 0xA1
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /**
60*4882a593Smuzhiyun * struct most_dci_obj - Direct Communication Interface
61*4882a593Smuzhiyun * @kobj:position in sysfs
62*4882a593Smuzhiyun * @usb_device: pointer to the usb device
63*4882a593Smuzhiyun * @reg_addr: register address for arbitrary DCI access
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun struct most_dci_obj {
66*4882a593Smuzhiyun struct device dev;
67*4882a593Smuzhiyun struct usb_device *usb_device;
68*4882a593Smuzhiyun u16 reg_addr;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define to_dci_obj(p) container_of(p, struct most_dci_obj, dev)
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun struct most_dev;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun struct clear_hold_work {
76*4882a593Smuzhiyun struct work_struct ws;
77*4882a593Smuzhiyun struct most_dev *mdev;
78*4882a593Smuzhiyun unsigned int channel;
79*4882a593Smuzhiyun int pipe;
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /**
85*4882a593Smuzhiyun * struct most_dev - holds all usb interface specific stuff
86*4882a593Smuzhiyun * @usb_device: pointer to usb device
87*4882a593Smuzhiyun * @iface: hardware interface
88*4882a593Smuzhiyun * @cap: channel capabilities
89*4882a593Smuzhiyun * @conf: channel configuration
90*4882a593Smuzhiyun * @dci: direct communication interface of hardware
91*4882a593Smuzhiyun * @ep_address: endpoint address table
92*4882a593Smuzhiyun * @description: device description
93*4882a593Smuzhiyun * @suffix: suffix for channel name
94*4882a593Smuzhiyun * @channel_lock: synchronize channel access
95*4882a593Smuzhiyun * @padding_active: indicates channel uses padding
96*4882a593Smuzhiyun * @is_channel_healthy: health status table of each channel
97*4882a593Smuzhiyun * @busy_urbs: list of anchored items
98*4882a593Smuzhiyun * @io_mutex: synchronize I/O with disconnect
99*4882a593Smuzhiyun * @link_stat_timer: timer for link status reports
100*4882a593Smuzhiyun * @poll_work_obj: work for polling link status
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun struct most_dev {
103*4882a593Smuzhiyun struct device dev;
104*4882a593Smuzhiyun struct usb_device *usb_device;
105*4882a593Smuzhiyun struct most_interface iface;
106*4882a593Smuzhiyun struct most_channel_capability *cap;
107*4882a593Smuzhiyun struct most_channel_config *conf;
108*4882a593Smuzhiyun struct most_dci_obj *dci;
109*4882a593Smuzhiyun u8 *ep_address;
110*4882a593Smuzhiyun char description[MAX_STRING_LEN];
111*4882a593Smuzhiyun char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
112*4882a593Smuzhiyun spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */
113*4882a593Smuzhiyun bool padding_active[MAX_NUM_ENDPOINTS];
114*4882a593Smuzhiyun bool is_channel_healthy[MAX_NUM_ENDPOINTS];
115*4882a593Smuzhiyun struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS];
116*4882a593Smuzhiyun struct usb_anchor *busy_urbs;
117*4882a593Smuzhiyun struct mutex io_mutex;
118*4882a593Smuzhiyun struct timer_list link_stat_timer;
119*4882a593Smuzhiyun struct work_struct poll_work_obj;
120*4882a593Smuzhiyun void (*on_netinfo)(struct most_interface *most_iface,
121*4882a593Smuzhiyun unsigned char link_state, unsigned char *addrs);
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define to_mdev(d) container_of(d, struct most_dev, iface)
125*4882a593Smuzhiyun #define to_mdev_from_dev(d) container_of(d, struct most_dev, dev)
126*4882a593Smuzhiyun #define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun static void wq_clear_halt(struct work_struct *wq_obj);
129*4882a593Smuzhiyun static void wq_netinfo(struct work_struct *wq_obj);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /**
132*4882a593Smuzhiyun * drci_rd_reg - read a DCI register
133*4882a593Smuzhiyun * @dev: usb device
134*4882a593Smuzhiyun * @reg: register address
135*4882a593Smuzhiyun * @buf: buffer to store data
136*4882a593Smuzhiyun *
137*4882a593Smuzhiyun * This is reads data from INIC's direct register communication interface
138*4882a593Smuzhiyun */
drci_rd_reg(struct usb_device * dev,u16 reg,u16 * buf)139*4882a593Smuzhiyun static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun int retval;
142*4882a593Smuzhiyun __le16 *dma_buf;
143*4882a593Smuzhiyun u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL);
146*4882a593Smuzhiyun if (!dma_buf)
147*4882a593Smuzhiyun return -ENOMEM;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
150*4882a593Smuzhiyun DRCI_READ_REQ, req_type,
151*4882a593Smuzhiyun 0x0000,
152*4882a593Smuzhiyun reg, dma_buf, sizeof(*dma_buf),
153*4882a593Smuzhiyun USB_CTRL_GET_TIMEOUT);
154*4882a593Smuzhiyun *buf = le16_to_cpu(*dma_buf);
155*4882a593Smuzhiyun kfree(dma_buf);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (retval < 0)
158*4882a593Smuzhiyun return retval;
159*4882a593Smuzhiyun return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /**
163*4882a593Smuzhiyun * drci_wr_reg - write a DCI register
164*4882a593Smuzhiyun * @dev: usb device
165*4882a593Smuzhiyun * @reg: register address
166*4882a593Smuzhiyun * @data: data to write
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * This is writes data to INIC's direct register communication interface
169*4882a593Smuzhiyun */
drci_wr_reg(struct usb_device * dev,u16 reg,u16 data)170*4882a593Smuzhiyun static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun return usb_control_msg(dev,
173*4882a593Smuzhiyun usb_sndctrlpipe(dev, 0),
174*4882a593Smuzhiyun DRCI_WRITE_REQ,
175*4882a593Smuzhiyun USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
176*4882a593Smuzhiyun data,
177*4882a593Smuzhiyun reg,
178*4882a593Smuzhiyun NULL,
179*4882a593Smuzhiyun 0,
180*4882a593Smuzhiyun USB_CTRL_SET_TIMEOUT);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
start_sync_ep(struct usb_device * usb_dev,u16 ep)183*4882a593Smuzhiyun static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun * get_stream_frame_size - calculate frame size of current configuration
190*4882a593Smuzhiyun * @dev: device structure
191*4882a593Smuzhiyun * @cfg: channel configuration
192*4882a593Smuzhiyun */
get_stream_frame_size(struct device * dev,struct most_channel_config * cfg)193*4882a593Smuzhiyun static unsigned int get_stream_frame_size(struct device *dev,
194*4882a593Smuzhiyun struct most_channel_config *cfg)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun unsigned int frame_size;
197*4882a593Smuzhiyun unsigned int sub_size = cfg->subbuffer_size;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (!sub_size) {
200*4882a593Smuzhiyun dev_warn(dev, "Misconfig: Subbuffer size zero.\n");
201*4882a593Smuzhiyun return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun switch (cfg->data_type) {
204*4882a593Smuzhiyun case MOST_CH_ISOC:
205*4882a593Smuzhiyun frame_size = AV_PACKETS_PER_XACT * sub_size;
206*4882a593Smuzhiyun break;
207*4882a593Smuzhiyun case MOST_CH_SYNC:
208*4882a593Smuzhiyun if (cfg->packets_per_xact == 0) {
209*4882a593Smuzhiyun dev_warn(dev, "Misconfig: Packets per XACT zero\n");
210*4882a593Smuzhiyun frame_size = 0;
211*4882a593Smuzhiyun } else if (cfg->packets_per_xact == 0xFF) {
212*4882a593Smuzhiyun frame_size = (USB_MTU / sub_size) * sub_size;
213*4882a593Smuzhiyun } else {
214*4882a593Smuzhiyun frame_size = cfg->packets_per_xact * sub_size;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun default:
218*4882a593Smuzhiyun dev_warn(dev, "Query frame size of non-streaming channel\n");
219*4882a593Smuzhiyun frame_size = 0;
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun return frame_size;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /**
226*4882a593Smuzhiyun * hdm_poison_channel - mark buffers of this channel as invalid
227*4882a593Smuzhiyun * @iface: pointer to the interface
228*4882a593Smuzhiyun * @channel: channel ID
229*4882a593Smuzhiyun *
230*4882a593Smuzhiyun * This unlinks all URBs submitted to the HCD,
231*4882a593Smuzhiyun * calls the associated completion function of the core and removes
232*4882a593Smuzhiyun * them from the list.
233*4882a593Smuzhiyun *
234*4882a593Smuzhiyun * Returns 0 on success or error code otherwise.
235*4882a593Smuzhiyun */
hdm_poison_channel(struct most_interface * iface,int channel)236*4882a593Smuzhiyun static int hdm_poison_channel(struct most_interface *iface, int channel)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(iface);
239*4882a593Smuzhiyun unsigned long flags;
240*4882a593Smuzhiyun spinlock_t *lock; /* temp. lock */
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun if (channel < 0 || channel >= iface->num_channels) {
243*4882a593Smuzhiyun dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
244*4882a593Smuzhiyun return -ECHRNG;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun lock = mdev->channel_lock + channel;
248*4882a593Smuzhiyun spin_lock_irqsave(lock, flags);
249*4882a593Smuzhiyun mdev->is_channel_healthy[channel] = false;
250*4882a593Smuzhiyun spin_unlock_irqrestore(lock, flags);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun cancel_work_sync(&mdev->clear_work[channel].ws);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
255*4882a593Smuzhiyun usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
256*4882a593Smuzhiyun if (mdev->padding_active[channel])
257*4882a593Smuzhiyun mdev->padding_active[channel] = false;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
260*4882a593Smuzhiyun del_timer_sync(&mdev->link_stat_timer);
261*4882a593Smuzhiyun cancel_work_sync(&mdev->poll_work_obj);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
264*4882a593Smuzhiyun return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * hdm_add_padding - add padding bytes
269*4882a593Smuzhiyun * @mdev: most device
270*4882a593Smuzhiyun * @channel: channel ID
271*4882a593Smuzhiyun * @mbo: buffer object
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * This inserts the INIC hardware specific padding bytes into a streaming
274*4882a593Smuzhiyun * channel's buffer
275*4882a593Smuzhiyun */
hdm_add_padding(struct most_dev * mdev,int channel,struct mbo * mbo)276*4882a593Smuzhiyun static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct most_channel_config *conf = &mdev->conf[channel];
279*4882a593Smuzhiyun unsigned int frame_size = get_stream_frame_size(&mdev->dev, conf);
280*4882a593Smuzhiyun unsigned int j, num_frames;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if (!frame_size)
283*4882a593Smuzhiyun return -EINVAL;
284*4882a593Smuzhiyun num_frames = mbo->buffer_length / frame_size;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (num_frames < 1) {
287*4882a593Smuzhiyun dev_err(&mdev->usb_device->dev,
288*4882a593Smuzhiyun "Missed minimal transfer unit.\n");
289*4882a593Smuzhiyun return -EINVAL;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun for (j = num_frames - 1; j > 0; j--)
293*4882a593Smuzhiyun memmove(mbo->virt_address + j * USB_MTU,
294*4882a593Smuzhiyun mbo->virt_address + j * frame_size,
295*4882a593Smuzhiyun frame_size);
296*4882a593Smuzhiyun mbo->buffer_length = num_frames * USB_MTU;
297*4882a593Smuzhiyun return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /**
301*4882a593Smuzhiyun * hdm_remove_padding - remove padding bytes
302*4882a593Smuzhiyun * @mdev: most device
303*4882a593Smuzhiyun * @channel: channel ID
304*4882a593Smuzhiyun * @mbo: buffer object
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun * This takes the INIC hardware specific padding bytes off a streaming
307*4882a593Smuzhiyun * channel's buffer.
308*4882a593Smuzhiyun */
hdm_remove_padding(struct most_dev * mdev,int channel,struct mbo * mbo)309*4882a593Smuzhiyun static int hdm_remove_padding(struct most_dev *mdev, int channel,
310*4882a593Smuzhiyun struct mbo *mbo)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct most_channel_config *const conf = &mdev->conf[channel];
313*4882a593Smuzhiyun unsigned int frame_size = get_stream_frame_size(&mdev->dev, conf);
314*4882a593Smuzhiyun unsigned int j, num_frames;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun if (!frame_size)
317*4882a593Smuzhiyun return -EINVAL;
318*4882a593Smuzhiyun num_frames = mbo->processed_length / USB_MTU;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun for (j = 1; j < num_frames; j++)
321*4882a593Smuzhiyun memmove(mbo->virt_address + frame_size * j,
322*4882a593Smuzhiyun mbo->virt_address + USB_MTU * j,
323*4882a593Smuzhiyun frame_size);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun mbo->processed_length = frame_size * num_frames;
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /**
330*4882a593Smuzhiyun * hdm_write_completion - completion function for submitted Tx URBs
331*4882a593Smuzhiyun * @urb: the URB that has been completed
332*4882a593Smuzhiyun *
333*4882a593Smuzhiyun * This checks the status of the completed URB. In case the URB has been
334*4882a593Smuzhiyun * unlinked before, it is immediately freed. On any other error the MBO
335*4882a593Smuzhiyun * transfer flag is set. On success it frees allocated resources and calls
336*4882a593Smuzhiyun * the completion function.
337*4882a593Smuzhiyun *
338*4882a593Smuzhiyun * Context: interrupt!
339*4882a593Smuzhiyun */
hdm_write_completion(struct urb * urb)340*4882a593Smuzhiyun static void hdm_write_completion(struct urb *urb)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun struct mbo *mbo = urb->context;
343*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(mbo->ifp);
344*4882a593Smuzhiyun unsigned int channel = mbo->hdm_channel_id;
345*4882a593Smuzhiyun spinlock_t *lock = mdev->channel_lock + channel;
346*4882a593Smuzhiyun unsigned long flags;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun spin_lock_irqsave(lock, flags);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun mbo->processed_length = 0;
351*4882a593Smuzhiyun mbo->status = MBO_E_INVAL;
352*4882a593Smuzhiyun if (likely(mdev->is_channel_healthy[channel])) {
353*4882a593Smuzhiyun switch (urb->status) {
354*4882a593Smuzhiyun case 0:
355*4882a593Smuzhiyun case -ESHUTDOWN:
356*4882a593Smuzhiyun mbo->processed_length = urb->actual_length;
357*4882a593Smuzhiyun mbo->status = MBO_SUCCESS;
358*4882a593Smuzhiyun break;
359*4882a593Smuzhiyun case -EPIPE:
360*4882a593Smuzhiyun dev_warn(&mdev->usb_device->dev,
361*4882a593Smuzhiyun "Broken pipe on ep%02x\n",
362*4882a593Smuzhiyun mdev->ep_address[channel]);
363*4882a593Smuzhiyun mdev->is_channel_healthy[channel] = false;
364*4882a593Smuzhiyun mdev->clear_work[channel].pipe = urb->pipe;
365*4882a593Smuzhiyun schedule_work(&mdev->clear_work[channel].ws);
366*4882a593Smuzhiyun break;
367*4882a593Smuzhiyun case -ENODEV:
368*4882a593Smuzhiyun case -EPROTO:
369*4882a593Smuzhiyun mbo->status = MBO_E_CLOSE;
370*4882a593Smuzhiyun break;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun spin_unlock_irqrestore(lock, flags);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (likely(mbo->complete))
377*4882a593Smuzhiyun mbo->complete(mbo);
378*4882a593Smuzhiyun usb_free_urb(urb);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /**
382*4882a593Smuzhiyun * hdm_read_completion - completion function for submitted Rx URBs
383*4882a593Smuzhiyun * @urb: the URB that has been completed
384*4882a593Smuzhiyun *
385*4882a593Smuzhiyun * This checks the status of the completed URB. In case the URB has been
386*4882a593Smuzhiyun * unlinked before it is immediately freed. On any other error the MBO transfer
387*4882a593Smuzhiyun * flag is set. On success it frees allocated resources, removes
388*4882a593Smuzhiyun * padding bytes -if necessary- and calls the completion function.
389*4882a593Smuzhiyun *
390*4882a593Smuzhiyun * Context: interrupt!
391*4882a593Smuzhiyun */
hdm_read_completion(struct urb * urb)392*4882a593Smuzhiyun static void hdm_read_completion(struct urb *urb)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct mbo *mbo = urb->context;
395*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(mbo->ifp);
396*4882a593Smuzhiyun unsigned int channel = mbo->hdm_channel_id;
397*4882a593Smuzhiyun struct device *dev = &mdev->usb_device->dev;
398*4882a593Smuzhiyun spinlock_t *lock = mdev->channel_lock + channel;
399*4882a593Smuzhiyun unsigned long flags;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun spin_lock_irqsave(lock, flags);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun mbo->processed_length = 0;
404*4882a593Smuzhiyun mbo->status = MBO_E_INVAL;
405*4882a593Smuzhiyun if (likely(mdev->is_channel_healthy[channel])) {
406*4882a593Smuzhiyun switch (urb->status) {
407*4882a593Smuzhiyun case 0:
408*4882a593Smuzhiyun case -ESHUTDOWN:
409*4882a593Smuzhiyun mbo->processed_length = urb->actual_length;
410*4882a593Smuzhiyun mbo->status = MBO_SUCCESS;
411*4882a593Smuzhiyun if (mdev->padding_active[channel] &&
412*4882a593Smuzhiyun hdm_remove_padding(mdev, channel, mbo)) {
413*4882a593Smuzhiyun mbo->processed_length = 0;
414*4882a593Smuzhiyun mbo->status = MBO_E_INVAL;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun break;
417*4882a593Smuzhiyun case -EPIPE:
418*4882a593Smuzhiyun dev_warn(dev, "Broken pipe on ep%02x\n",
419*4882a593Smuzhiyun mdev->ep_address[channel]);
420*4882a593Smuzhiyun mdev->is_channel_healthy[channel] = false;
421*4882a593Smuzhiyun mdev->clear_work[channel].pipe = urb->pipe;
422*4882a593Smuzhiyun schedule_work(&mdev->clear_work[channel].ws);
423*4882a593Smuzhiyun break;
424*4882a593Smuzhiyun case -ENODEV:
425*4882a593Smuzhiyun case -EPROTO:
426*4882a593Smuzhiyun mbo->status = MBO_E_CLOSE;
427*4882a593Smuzhiyun break;
428*4882a593Smuzhiyun case -EOVERFLOW:
429*4882a593Smuzhiyun dev_warn(dev, "Babble on ep%02x\n",
430*4882a593Smuzhiyun mdev->ep_address[channel]);
431*4882a593Smuzhiyun break;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun spin_unlock_irqrestore(lock, flags);
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun if (likely(mbo->complete))
438*4882a593Smuzhiyun mbo->complete(mbo);
439*4882a593Smuzhiyun usb_free_urb(urb);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun /**
443*4882a593Smuzhiyun * hdm_enqueue - receive a buffer to be used for data transfer
444*4882a593Smuzhiyun * @iface: interface to enqueue to
445*4882a593Smuzhiyun * @channel: ID of the channel
446*4882a593Smuzhiyun * @mbo: pointer to the buffer object
447*4882a593Smuzhiyun *
448*4882a593Smuzhiyun * This allocates a new URB and fills it according to the channel
449*4882a593Smuzhiyun * that is being used for transmission of data. Before the URB is
450*4882a593Smuzhiyun * submitted it is stored in the private anchor list.
451*4882a593Smuzhiyun *
452*4882a593Smuzhiyun * Returns 0 on success. On any error the URB is freed and a error code
453*4882a593Smuzhiyun * is returned.
454*4882a593Smuzhiyun *
455*4882a593Smuzhiyun * Context: Could in _some_ cases be interrupt!
456*4882a593Smuzhiyun */
hdm_enqueue(struct most_interface * iface,int channel,struct mbo * mbo)457*4882a593Smuzhiyun static int hdm_enqueue(struct most_interface *iface, int channel,
458*4882a593Smuzhiyun struct mbo *mbo)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(iface);
461*4882a593Smuzhiyun struct most_channel_config *conf;
462*4882a593Smuzhiyun int retval = 0;
463*4882a593Smuzhiyun struct urb *urb;
464*4882a593Smuzhiyun unsigned long length;
465*4882a593Smuzhiyun void *virt_address;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (!mbo)
468*4882a593Smuzhiyun return -EINVAL;
469*4882a593Smuzhiyun if (iface->num_channels <= channel || channel < 0)
470*4882a593Smuzhiyun return -ECHRNG;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_KERNEL);
473*4882a593Smuzhiyun if (!urb)
474*4882a593Smuzhiyun return -ENOMEM;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun conf = &mdev->conf[channel];
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
479*4882a593Smuzhiyun if (!mdev->usb_device) {
480*4882a593Smuzhiyun retval = -ENODEV;
481*4882a593Smuzhiyun goto err_free_urb;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
485*4882a593Smuzhiyun hdm_add_padding(mdev, channel, mbo)) {
486*4882a593Smuzhiyun retval = -EINVAL;
487*4882a593Smuzhiyun goto err_free_urb;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun urb->transfer_dma = mbo->bus_address;
491*4882a593Smuzhiyun virt_address = mbo->virt_address;
492*4882a593Smuzhiyun length = mbo->buffer_length;
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun if (conf->direction & MOST_CH_TX) {
495*4882a593Smuzhiyun usb_fill_bulk_urb(urb, mdev->usb_device,
496*4882a593Smuzhiyun usb_sndbulkpipe(mdev->usb_device,
497*4882a593Smuzhiyun mdev->ep_address[channel]),
498*4882a593Smuzhiyun virt_address,
499*4882a593Smuzhiyun length,
500*4882a593Smuzhiyun hdm_write_completion,
501*4882a593Smuzhiyun mbo);
502*4882a593Smuzhiyun if (conf->data_type != MOST_CH_ISOC &&
503*4882a593Smuzhiyun conf->data_type != MOST_CH_SYNC)
504*4882a593Smuzhiyun urb->transfer_flags |= URB_ZERO_PACKET;
505*4882a593Smuzhiyun } else {
506*4882a593Smuzhiyun usb_fill_bulk_urb(urb, mdev->usb_device,
507*4882a593Smuzhiyun usb_rcvbulkpipe(mdev->usb_device,
508*4882a593Smuzhiyun mdev->ep_address[channel]),
509*4882a593Smuzhiyun virt_address,
510*4882a593Smuzhiyun length + conf->extra_len,
511*4882a593Smuzhiyun hdm_read_completion,
512*4882a593Smuzhiyun mbo);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun retval = usb_submit_urb(urb, GFP_KERNEL);
519*4882a593Smuzhiyun if (retval) {
520*4882a593Smuzhiyun dev_err(&mdev->usb_device->dev,
521*4882a593Smuzhiyun "URB submit failed with error %d.\n", retval);
522*4882a593Smuzhiyun goto err_unanchor_urb;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
525*4882a593Smuzhiyun return 0;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun err_unanchor_urb:
528*4882a593Smuzhiyun usb_unanchor_urb(urb);
529*4882a593Smuzhiyun err_free_urb:
530*4882a593Smuzhiyun usb_free_urb(urb);
531*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
532*4882a593Smuzhiyun return retval;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
hdm_dma_alloc(struct mbo * mbo,u32 size)535*4882a593Smuzhiyun static void *hdm_dma_alloc(struct mbo *mbo, u32 size)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(mbo->ifp);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun return usb_alloc_coherent(mdev->usb_device, size, GFP_KERNEL,
540*4882a593Smuzhiyun &mbo->bus_address);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
hdm_dma_free(struct mbo * mbo,u32 size)543*4882a593Smuzhiyun static void hdm_dma_free(struct mbo *mbo, u32 size)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(mbo->ifp);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun usb_free_coherent(mdev->usb_device, size, mbo->virt_address,
548*4882a593Smuzhiyun mbo->bus_address);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun /**
552*4882a593Smuzhiyun * hdm_configure_channel - receive channel configuration from core
553*4882a593Smuzhiyun * @iface: interface
554*4882a593Smuzhiyun * @channel: channel ID
555*4882a593Smuzhiyun * @conf: structure that holds the configuration information
556*4882a593Smuzhiyun *
557*4882a593Smuzhiyun * The attached network interface controller (NIC) supports a padding mode
558*4882a593Smuzhiyun * to avoid short packets on USB, hence increasing the performance due to a
559*4882a593Smuzhiyun * lower interrupt load. This mode is default for synchronous data and can
560*4882a593Smuzhiyun * be switched on for isochronous data. In case padding is active the
561*4882a593Smuzhiyun * driver needs to know the frame size of the payload in order to calculate
562*4882a593Smuzhiyun * the number of bytes it needs to pad when transmitting or to cut off when
563*4882a593Smuzhiyun * receiving data.
564*4882a593Smuzhiyun *
565*4882a593Smuzhiyun */
hdm_configure_channel(struct most_interface * iface,int channel,struct most_channel_config * conf)566*4882a593Smuzhiyun static int hdm_configure_channel(struct most_interface *iface, int channel,
567*4882a593Smuzhiyun struct most_channel_config *conf)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun unsigned int num_frames;
570*4882a593Smuzhiyun unsigned int frame_size;
571*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(iface);
572*4882a593Smuzhiyun struct device *dev = &mdev->usb_device->dev;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun if (!conf) {
575*4882a593Smuzhiyun dev_err(dev, "Bad config pointer.\n");
576*4882a593Smuzhiyun return -EINVAL;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun if (channel < 0 || channel >= iface->num_channels) {
579*4882a593Smuzhiyun dev_err(dev, "Channel ID out of range.\n");
580*4882a593Smuzhiyun return -EINVAL;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun mdev->is_channel_healthy[channel] = true;
584*4882a593Smuzhiyun mdev->clear_work[channel].channel = channel;
585*4882a593Smuzhiyun mdev->clear_work[channel].mdev = mdev;
586*4882a593Smuzhiyun INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (!conf->num_buffers || !conf->buffer_size) {
589*4882a593Smuzhiyun dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
590*4882a593Smuzhiyun return -EINVAL;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun if (conf->data_type != MOST_CH_SYNC &&
594*4882a593Smuzhiyun !(conf->data_type == MOST_CH_ISOC &&
595*4882a593Smuzhiyun conf->packets_per_xact != 0xFF)) {
596*4882a593Smuzhiyun mdev->padding_active[channel] = false;
597*4882a593Smuzhiyun /*
598*4882a593Smuzhiyun * Since the NIC's padding mode is not going to be
599*4882a593Smuzhiyun * used, we can skip the frame size calculations and
600*4882a593Smuzhiyun * move directly on to exit.
601*4882a593Smuzhiyun */
602*4882a593Smuzhiyun goto exit;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun mdev->padding_active[channel] = true;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun frame_size = get_stream_frame_size(&mdev->dev, conf);
608*4882a593Smuzhiyun if (frame_size == 0 || frame_size > USB_MTU) {
609*4882a593Smuzhiyun dev_warn(dev, "Misconfig: frame size wrong\n");
610*4882a593Smuzhiyun return -EINVAL;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun num_frames = conf->buffer_size / frame_size;
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (conf->buffer_size % frame_size) {
616*4882a593Smuzhiyun u16 old_size = conf->buffer_size;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun conf->buffer_size = num_frames * frame_size;
619*4882a593Smuzhiyun dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
620*4882a593Smuzhiyun mdev->suffix[channel], old_size, conf->buffer_size);
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /* calculate extra length to comply w/ HW padding */
624*4882a593Smuzhiyun conf->extra_len = num_frames * (USB_MTU - frame_size);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun exit:
627*4882a593Smuzhiyun mdev->conf[channel] = *conf;
628*4882a593Smuzhiyun if (conf->data_type == MOST_CH_ASYNC) {
629*4882a593Smuzhiyun u16 ep = mdev->ep_address[channel];
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (start_sync_ep(mdev->usb_device, ep) < 0)
632*4882a593Smuzhiyun dev_warn(dev, "sync for ep%02x failed", ep);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun return 0;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /**
638*4882a593Smuzhiyun * hdm_request_netinfo - request network information
639*4882a593Smuzhiyun * @iface: pointer to interface
640*4882a593Smuzhiyun * @channel: channel ID
641*4882a593Smuzhiyun *
642*4882a593Smuzhiyun * This is used as trigger to set up the link status timer that
643*4882a593Smuzhiyun * polls for the NI state of the INIC every 2 seconds.
644*4882a593Smuzhiyun *
645*4882a593Smuzhiyun */
hdm_request_netinfo(struct most_interface * iface,int channel,void (* on_netinfo)(struct most_interface *,unsigned char,unsigned char *))646*4882a593Smuzhiyun static void hdm_request_netinfo(struct most_interface *iface, int channel,
647*4882a593Smuzhiyun void (*on_netinfo)(struct most_interface *,
648*4882a593Smuzhiyun unsigned char,
649*4882a593Smuzhiyun unsigned char *))
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun struct most_dev *mdev = to_mdev(iface);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun mdev->on_netinfo = on_netinfo;
654*4882a593Smuzhiyun if (!on_netinfo)
655*4882a593Smuzhiyun return;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun mdev->link_stat_timer.expires = jiffies + HZ;
658*4882a593Smuzhiyun mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun /**
662*4882a593Smuzhiyun * link_stat_timer_handler - schedule work obtaining mac address and link status
663*4882a593Smuzhiyun * @data: pointer to USB device instance
664*4882a593Smuzhiyun *
665*4882a593Smuzhiyun * The handler runs in interrupt context. That's why we need to defer the
666*4882a593Smuzhiyun * tasks to a work queue.
667*4882a593Smuzhiyun */
link_stat_timer_handler(struct timer_list * t)668*4882a593Smuzhiyun static void link_stat_timer_handler(struct timer_list *t)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun struct most_dev *mdev = from_timer(mdev, t, link_stat_timer);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun schedule_work(&mdev->poll_work_obj);
673*4882a593Smuzhiyun mdev->link_stat_timer.expires = jiffies + (2 * HZ);
674*4882a593Smuzhiyun add_timer(&mdev->link_stat_timer);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun /**
678*4882a593Smuzhiyun * wq_netinfo - work queue function to deliver latest networking information
679*4882a593Smuzhiyun * @wq_obj: object that holds data for our deferred work to do
680*4882a593Smuzhiyun *
681*4882a593Smuzhiyun * This retrieves the network interface status of the USB INIC
682*4882a593Smuzhiyun */
wq_netinfo(struct work_struct * wq_obj)683*4882a593Smuzhiyun static void wq_netinfo(struct work_struct *wq_obj)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun struct most_dev *mdev = to_mdev_from_work(wq_obj);
686*4882a593Smuzhiyun struct usb_device *usb_device = mdev->usb_device;
687*4882a593Smuzhiyun struct device *dev = &usb_device->dev;
688*4882a593Smuzhiyun u16 hi, mi, lo, link;
689*4882a593Smuzhiyun u8 hw_addr[6];
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi)) {
692*4882a593Smuzhiyun dev_err(dev, "Vendor request 'hw_addr_hi' failed\n");
693*4882a593Smuzhiyun return;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi)) {
697*4882a593Smuzhiyun dev_err(dev, "Vendor request 'hw_addr_mid' failed\n");
698*4882a593Smuzhiyun return;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo)) {
702*4882a593Smuzhiyun dev_err(dev, "Vendor request 'hw_addr_low' failed\n");
703*4882a593Smuzhiyun return;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link)) {
707*4882a593Smuzhiyun dev_err(dev, "Vendor request 'link status' failed\n");
708*4882a593Smuzhiyun return;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun hw_addr[0] = hi >> 8;
712*4882a593Smuzhiyun hw_addr[1] = hi;
713*4882a593Smuzhiyun hw_addr[2] = mi >> 8;
714*4882a593Smuzhiyun hw_addr[3] = mi;
715*4882a593Smuzhiyun hw_addr[4] = lo >> 8;
716*4882a593Smuzhiyun hw_addr[5] = lo;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (mdev->on_netinfo)
719*4882a593Smuzhiyun mdev->on_netinfo(&mdev->iface, link, hw_addr);
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun /**
723*4882a593Smuzhiyun * wq_clear_halt - work queue function
724*4882a593Smuzhiyun * @wq_obj: work_struct object to execute
725*4882a593Smuzhiyun *
726*4882a593Smuzhiyun * This sends a clear_halt to the given USB pipe.
727*4882a593Smuzhiyun */
wq_clear_halt(struct work_struct * wq_obj)728*4882a593Smuzhiyun static void wq_clear_halt(struct work_struct *wq_obj)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj);
731*4882a593Smuzhiyun struct most_dev *mdev = clear_work->mdev;
732*4882a593Smuzhiyun unsigned int channel = clear_work->channel;
733*4882a593Smuzhiyun int pipe = clear_work->pipe;
734*4882a593Smuzhiyun int snd_pipe;
735*4882a593Smuzhiyun int peer;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
738*4882a593Smuzhiyun most_stop_enqueue(&mdev->iface, channel);
739*4882a593Smuzhiyun usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
740*4882a593Smuzhiyun if (usb_clear_halt(mdev->usb_device, pipe))
741*4882a593Smuzhiyun dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun /* If the functional Stall condition has been set on an
744*4882a593Smuzhiyun * asynchronous rx channel, we need to clear the tx channel
745*4882a593Smuzhiyun * too, since the hardware runs its clean-up sequence on both
746*4882a593Smuzhiyun * channels, as they are physically one on the network.
747*4882a593Smuzhiyun *
748*4882a593Smuzhiyun * The USB interface that exposes the asynchronous channels
749*4882a593Smuzhiyun * contains always two endpoints, and two only.
750*4882a593Smuzhiyun */
751*4882a593Smuzhiyun if (mdev->conf[channel].data_type == MOST_CH_ASYNC &&
752*4882a593Smuzhiyun mdev->conf[channel].direction == MOST_CH_RX) {
753*4882a593Smuzhiyun if (channel == 0)
754*4882a593Smuzhiyun peer = 1;
755*4882a593Smuzhiyun else
756*4882a593Smuzhiyun peer = 0;
757*4882a593Smuzhiyun snd_pipe = usb_sndbulkpipe(mdev->usb_device,
758*4882a593Smuzhiyun mdev->ep_address[peer]);
759*4882a593Smuzhiyun usb_clear_halt(mdev->usb_device, snd_pipe);
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun mdev->is_channel_healthy[channel] = true;
762*4882a593Smuzhiyun most_resume_enqueue(&mdev->iface, channel);
763*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun /**
767*4882a593Smuzhiyun * hdm_usb_fops - file operation table for USB driver
768*4882a593Smuzhiyun */
769*4882a593Smuzhiyun static const struct file_operations hdm_usb_fops = {
770*4882a593Smuzhiyun .owner = THIS_MODULE,
771*4882a593Smuzhiyun };
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun /**
774*4882a593Smuzhiyun * usb_device_id - ID table for HCD device probing
775*4882a593Smuzhiyun */
776*4882a593Smuzhiyun static const struct usb_device_id usbid[] = {
777*4882a593Smuzhiyun { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
778*4882a593Smuzhiyun { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), },
779*4882a593Smuzhiyun { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), },
780*4882a593Smuzhiyun { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), },
781*4882a593Smuzhiyun { } /* Terminating entry */
782*4882a593Smuzhiyun };
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun struct regs {
785*4882a593Smuzhiyun const char *name;
786*4882a593Smuzhiyun u16 reg;
787*4882a593Smuzhiyun };
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun static const struct regs ro_regs[] = {
790*4882a593Smuzhiyun { "ni_state", DRCI_REG_NI_STATE },
791*4882a593Smuzhiyun { "packet_bandwidth", DRCI_REG_PACKET_BW },
792*4882a593Smuzhiyun { "node_address", DRCI_REG_NODE_ADDR },
793*4882a593Smuzhiyun { "node_position", DRCI_REG_NODE_POS },
794*4882a593Smuzhiyun };
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun static const struct regs rw_regs[] = {
797*4882a593Smuzhiyun { "mep_filter", DRCI_REG_MEP_FILTER },
798*4882a593Smuzhiyun { "mep_hash0", DRCI_REG_HASH_TBL0 },
799*4882a593Smuzhiyun { "mep_hash1", DRCI_REG_HASH_TBL1 },
800*4882a593Smuzhiyun { "mep_hash2", DRCI_REG_HASH_TBL2 },
801*4882a593Smuzhiyun { "mep_hash3", DRCI_REG_HASH_TBL3 },
802*4882a593Smuzhiyun { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI },
803*4882a593Smuzhiyun { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI },
804*4882a593Smuzhiyun { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO },
805*4882a593Smuzhiyun };
806*4882a593Smuzhiyun
get_stat_reg_addr(const struct regs * regs,int size,const char * name,u16 * reg_addr)807*4882a593Smuzhiyun static int get_stat_reg_addr(const struct regs *regs, int size,
808*4882a593Smuzhiyun const char *name, u16 *reg_addr)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun int i;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun for (i = 0; i < size; i++) {
813*4882a593Smuzhiyun if (sysfs_streq(name, regs[i].name)) {
814*4882a593Smuzhiyun *reg_addr = regs[i].reg;
815*4882a593Smuzhiyun return 0;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun return -EINVAL;
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun #define get_static_reg_addr(regs, name, reg_addr) \
822*4882a593Smuzhiyun get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
823*4882a593Smuzhiyun
value_show(struct device * dev,struct device_attribute * attr,char * buf)824*4882a593Smuzhiyun static ssize_t value_show(struct device *dev, struct device_attribute *attr,
825*4882a593Smuzhiyun char *buf)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun const char *name = attr->attr.name;
828*4882a593Smuzhiyun struct most_dci_obj *dci_obj = to_dci_obj(dev);
829*4882a593Smuzhiyun u16 val;
830*4882a593Smuzhiyun u16 reg_addr;
831*4882a593Smuzhiyun int err;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun if (sysfs_streq(name, "arb_address"))
834*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun if (sysfs_streq(name, "arb_value"))
837*4882a593Smuzhiyun reg_addr = dci_obj->reg_addr;
838*4882a593Smuzhiyun else if (get_static_reg_addr(ro_regs, name, ®_addr) &&
839*4882a593Smuzhiyun get_static_reg_addr(rw_regs, name, ®_addr))
840*4882a593Smuzhiyun return -EINVAL;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val);
843*4882a593Smuzhiyun if (err < 0)
844*4882a593Smuzhiyun return err;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%04x\n", val);
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
value_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)849*4882a593Smuzhiyun static ssize_t value_store(struct device *dev, struct device_attribute *attr,
850*4882a593Smuzhiyun const char *buf, size_t count)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun u16 val;
853*4882a593Smuzhiyun u16 reg_addr;
854*4882a593Smuzhiyun const char *name = attr->attr.name;
855*4882a593Smuzhiyun struct most_dci_obj *dci_obj = to_dci_obj(dev);
856*4882a593Smuzhiyun struct usb_device *usb_dev = dci_obj->usb_device;
857*4882a593Smuzhiyun int err;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun err = kstrtou16(buf, 16, &val);
860*4882a593Smuzhiyun if (err)
861*4882a593Smuzhiyun return err;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun if (sysfs_streq(name, "arb_address")) {
864*4882a593Smuzhiyun dci_obj->reg_addr = val;
865*4882a593Smuzhiyun return count;
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun if (sysfs_streq(name, "arb_value"))
869*4882a593Smuzhiyun err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
870*4882a593Smuzhiyun else if (sysfs_streq(name, "sync_ep"))
871*4882a593Smuzhiyun err = start_sync_ep(usb_dev, val);
872*4882a593Smuzhiyun else if (!get_static_reg_addr(rw_regs, name, ®_addr))
873*4882a593Smuzhiyun err = drci_wr_reg(usb_dev, reg_addr, val);
874*4882a593Smuzhiyun else
875*4882a593Smuzhiyun return -EINVAL;
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun if (err < 0)
878*4882a593Smuzhiyun return err;
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun return count;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun static DEVICE_ATTR(ni_state, 0444, value_show, NULL);
884*4882a593Smuzhiyun static DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL);
885*4882a593Smuzhiyun static DEVICE_ATTR(node_address, 0444, value_show, NULL);
886*4882a593Smuzhiyun static DEVICE_ATTR(node_position, 0444, value_show, NULL);
887*4882a593Smuzhiyun static DEVICE_ATTR(sync_ep, 0200, NULL, value_store);
888*4882a593Smuzhiyun static DEVICE_ATTR(mep_filter, 0644, value_show, value_store);
889*4882a593Smuzhiyun static DEVICE_ATTR(mep_hash0, 0644, value_show, value_store);
890*4882a593Smuzhiyun static DEVICE_ATTR(mep_hash1, 0644, value_show, value_store);
891*4882a593Smuzhiyun static DEVICE_ATTR(mep_hash2, 0644, value_show, value_store);
892*4882a593Smuzhiyun static DEVICE_ATTR(mep_hash3, 0644, value_show, value_store);
893*4882a593Smuzhiyun static DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store);
894*4882a593Smuzhiyun static DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store);
895*4882a593Smuzhiyun static DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store);
896*4882a593Smuzhiyun static DEVICE_ATTR(arb_address, 0644, value_show, value_store);
897*4882a593Smuzhiyun static DEVICE_ATTR(arb_value, 0644, value_show, value_store);
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun static struct attribute *dci_attrs[] = {
900*4882a593Smuzhiyun &dev_attr_ni_state.attr,
901*4882a593Smuzhiyun &dev_attr_packet_bandwidth.attr,
902*4882a593Smuzhiyun &dev_attr_node_address.attr,
903*4882a593Smuzhiyun &dev_attr_node_position.attr,
904*4882a593Smuzhiyun &dev_attr_sync_ep.attr,
905*4882a593Smuzhiyun &dev_attr_mep_filter.attr,
906*4882a593Smuzhiyun &dev_attr_mep_hash0.attr,
907*4882a593Smuzhiyun &dev_attr_mep_hash1.attr,
908*4882a593Smuzhiyun &dev_attr_mep_hash2.attr,
909*4882a593Smuzhiyun &dev_attr_mep_hash3.attr,
910*4882a593Smuzhiyun &dev_attr_mep_eui48_hi.attr,
911*4882a593Smuzhiyun &dev_attr_mep_eui48_mi.attr,
912*4882a593Smuzhiyun &dev_attr_mep_eui48_lo.attr,
913*4882a593Smuzhiyun &dev_attr_arb_address.attr,
914*4882a593Smuzhiyun &dev_attr_arb_value.attr,
915*4882a593Smuzhiyun NULL,
916*4882a593Smuzhiyun };
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun ATTRIBUTE_GROUPS(dci);
919*4882a593Smuzhiyun
release_dci(struct device * dev)920*4882a593Smuzhiyun static void release_dci(struct device *dev)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun struct most_dci_obj *dci = to_dci_obj(dev);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun put_device(dev->parent);
925*4882a593Smuzhiyun kfree(dci);
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
release_mdev(struct device * dev)928*4882a593Smuzhiyun static void release_mdev(struct device *dev)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun struct most_dev *mdev = to_mdev_from_dev(dev);
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun kfree(mdev);
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun /**
935*4882a593Smuzhiyun * hdm_probe - probe function of USB device driver
936*4882a593Smuzhiyun * @interface: Interface of the attached USB device
937*4882a593Smuzhiyun * @id: Pointer to the USB ID table.
938*4882a593Smuzhiyun *
939*4882a593Smuzhiyun * This allocates and initializes the device instance, adds the new
940*4882a593Smuzhiyun * entry to the internal list, scans the USB descriptors and registers
941*4882a593Smuzhiyun * the interface with the core.
942*4882a593Smuzhiyun * Additionally, the DCI objects are created and the hardware is sync'd.
943*4882a593Smuzhiyun *
944*4882a593Smuzhiyun * Return 0 on success. In case of an error a negative number is returned.
945*4882a593Smuzhiyun */
946*4882a593Smuzhiyun static int
hdm_probe(struct usb_interface * interface,const struct usb_device_id * id)947*4882a593Smuzhiyun hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
948*4882a593Smuzhiyun {
949*4882a593Smuzhiyun struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
950*4882a593Smuzhiyun struct usb_device *usb_dev = interface_to_usbdev(interface);
951*4882a593Smuzhiyun struct device *dev = &usb_dev->dev;
952*4882a593Smuzhiyun struct most_dev *mdev;
953*4882a593Smuzhiyun unsigned int i;
954*4882a593Smuzhiyun unsigned int num_endpoints;
955*4882a593Smuzhiyun struct most_channel_capability *tmp_cap;
956*4882a593Smuzhiyun struct usb_endpoint_descriptor *ep_desc;
957*4882a593Smuzhiyun int ret = -ENOMEM;
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
960*4882a593Smuzhiyun if (!mdev)
961*4882a593Smuzhiyun return -ENOMEM;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun usb_set_intfdata(interface, mdev);
964*4882a593Smuzhiyun num_endpoints = usb_iface_desc->desc.bNumEndpoints;
965*4882a593Smuzhiyun if (num_endpoints > MAX_NUM_ENDPOINTS) {
966*4882a593Smuzhiyun kfree(mdev);
967*4882a593Smuzhiyun return -EINVAL;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun mutex_init(&mdev->io_mutex);
970*4882a593Smuzhiyun INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
971*4882a593Smuzhiyun timer_setup(&mdev->link_stat_timer, link_stat_timer_handler, 0);
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun mdev->usb_device = usb_dev;
974*4882a593Smuzhiyun mdev->link_stat_timer.expires = jiffies + (2 * HZ);
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun mdev->iface.mod = hdm_usb_fops.owner;
977*4882a593Smuzhiyun mdev->iface.dev = &mdev->dev;
978*4882a593Smuzhiyun mdev->iface.driver_dev = &interface->dev;
979*4882a593Smuzhiyun mdev->iface.interface = ITYPE_USB;
980*4882a593Smuzhiyun mdev->iface.configure = hdm_configure_channel;
981*4882a593Smuzhiyun mdev->iface.request_netinfo = hdm_request_netinfo;
982*4882a593Smuzhiyun mdev->iface.enqueue = hdm_enqueue;
983*4882a593Smuzhiyun mdev->iface.poison_channel = hdm_poison_channel;
984*4882a593Smuzhiyun mdev->iface.dma_alloc = hdm_dma_alloc;
985*4882a593Smuzhiyun mdev->iface.dma_free = hdm_dma_free;
986*4882a593Smuzhiyun mdev->iface.description = mdev->description;
987*4882a593Smuzhiyun mdev->iface.num_channels = num_endpoints;
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun snprintf(mdev->description, sizeof(mdev->description),
990*4882a593Smuzhiyun "%d-%s:%d.%d",
991*4882a593Smuzhiyun usb_dev->bus->busnum,
992*4882a593Smuzhiyun usb_dev->devpath,
993*4882a593Smuzhiyun usb_dev->config->desc.bConfigurationValue,
994*4882a593Smuzhiyun usb_iface_desc->desc.bInterfaceNumber);
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun mdev->dev.init_name = mdev->description;
997*4882a593Smuzhiyun mdev->dev.parent = &interface->dev;
998*4882a593Smuzhiyun mdev->dev.release = release_mdev;
999*4882a593Smuzhiyun mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
1000*4882a593Smuzhiyun if (!mdev->conf)
1001*4882a593Smuzhiyun goto err_free_mdev;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
1004*4882a593Smuzhiyun if (!mdev->cap)
1005*4882a593Smuzhiyun goto err_free_conf;
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun mdev->iface.channel_vector = mdev->cap;
1008*4882a593Smuzhiyun mdev->ep_address =
1009*4882a593Smuzhiyun kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
1010*4882a593Smuzhiyun if (!mdev->ep_address)
1011*4882a593Smuzhiyun goto err_free_cap;
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun mdev->busy_urbs =
1014*4882a593Smuzhiyun kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
1015*4882a593Smuzhiyun if (!mdev->busy_urbs)
1016*4882a593Smuzhiyun goto err_free_ep_address;
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun tmp_cap = mdev->cap;
1019*4882a593Smuzhiyun for (i = 0; i < num_endpoints; i++) {
1020*4882a593Smuzhiyun ep_desc = &usb_iface_desc->endpoint[i].desc;
1021*4882a593Smuzhiyun mdev->ep_address[i] = ep_desc->bEndpointAddress;
1022*4882a593Smuzhiyun mdev->padding_active[i] = false;
1023*4882a593Smuzhiyun mdev->is_channel_healthy[i] = true;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
1026*4882a593Smuzhiyun mdev->ep_address[i]);
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun tmp_cap->name_suffix = &mdev->suffix[i][0];
1029*4882a593Smuzhiyun tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
1030*4882a593Smuzhiyun tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
1031*4882a593Smuzhiyun tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
1032*4882a593Smuzhiyun tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
1033*4882a593Smuzhiyun tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
1034*4882a593Smuzhiyun MOST_CH_ISOC | MOST_CH_SYNC;
1035*4882a593Smuzhiyun if (usb_endpoint_dir_in(ep_desc))
1036*4882a593Smuzhiyun tmp_cap->direction = MOST_CH_RX;
1037*4882a593Smuzhiyun else
1038*4882a593Smuzhiyun tmp_cap->direction = MOST_CH_TX;
1039*4882a593Smuzhiyun tmp_cap++;
1040*4882a593Smuzhiyun init_usb_anchor(&mdev->busy_urbs[i]);
1041*4882a593Smuzhiyun spin_lock_init(&mdev->channel_lock[i]);
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun dev_dbg(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
1044*4882a593Smuzhiyun le16_to_cpu(usb_dev->descriptor.idVendor),
1045*4882a593Smuzhiyun le16_to_cpu(usb_dev->descriptor.idProduct),
1046*4882a593Smuzhiyun usb_dev->bus->busnum,
1047*4882a593Smuzhiyun usb_dev->devnum);
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun dev_dbg(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
1050*4882a593Smuzhiyun usb_dev->bus->busnum,
1051*4882a593Smuzhiyun usb_dev->devpath,
1052*4882a593Smuzhiyun usb_dev->config->desc.bConfigurationValue,
1053*4882a593Smuzhiyun usb_iface_desc->desc.bInterfaceNumber);
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun ret = most_register_interface(&mdev->iface);
1056*4882a593Smuzhiyun if (ret)
1057*4882a593Smuzhiyun goto err_free_busy_urbs;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
1060*4882a593Smuzhiyun if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
1061*4882a593Smuzhiyun le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
1062*4882a593Smuzhiyun le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
1063*4882a593Smuzhiyun mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL);
1064*4882a593Smuzhiyun if (!mdev->dci) {
1065*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1066*4882a593Smuzhiyun most_deregister_interface(&mdev->iface);
1067*4882a593Smuzhiyun ret = -ENOMEM;
1068*4882a593Smuzhiyun goto err_free_busy_urbs;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun mdev->dci->dev.init_name = "dci";
1072*4882a593Smuzhiyun mdev->dci->dev.parent = get_device(mdev->iface.dev);
1073*4882a593Smuzhiyun mdev->dci->dev.groups = dci_groups;
1074*4882a593Smuzhiyun mdev->dci->dev.release = release_dci;
1075*4882a593Smuzhiyun if (device_register(&mdev->dci->dev)) {
1076*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1077*4882a593Smuzhiyun most_deregister_interface(&mdev->iface);
1078*4882a593Smuzhiyun ret = -ENOMEM;
1079*4882a593Smuzhiyun goto err_free_dci;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun mdev->dci->usb_device = mdev->usb_device;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1084*4882a593Smuzhiyun return 0;
1085*4882a593Smuzhiyun err_free_dci:
1086*4882a593Smuzhiyun put_device(&mdev->dci->dev);
1087*4882a593Smuzhiyun err_free_busy_urbs:
1088*4882a593Smuzhiyun kfree(mdev->busy_urbs);
1089*4882a593Smuzhiyun err_free_ep_address:
1090*4882a593Smuzhiyun kfree(mdev->ep_address);
1091*4882a593Smuzhiyun err_free_cap:
1092*4882a593Smuzhiyun kfree(mdev->cap);
1093*4882a593Smuzhiyun err_free_conf:
1094*4882a593Smuzhiyun kfree(mdev->conf);
1095*4882a593Smuzhiyun err_free_mdev:
1096*4882a593Smuzhiyun put_device(&mdev->dev);
1097*4882a593Smuzhiyun return ret;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun /**
1101*4882a593Smuzhiyun * hdm_disconnect - disconnect function of USB device driver
1102*4882a593Smuzhiyun * @interface: Interface of the attached USB device
1103*4882a593Smuzhiyun *
1104*4882a593Smuzhiyun * This deregisters the interface with the core, removes the kernel timer
1105*4882a593Smuzhiyun * and frees resources.
1106*4882a593Smuzhiyun *
1107*4882a593Smuzhiyun * Context: hub kernel thread
1108*4882a593Smuzhiyun */
hdm_disconnect(struct usb_interface * interface)1109*4882a593Smuzhiyun static void hdm_disconnect(struct usb_interface *interface)
1110*4882a593Smuzhiyun {
1111*4882a593Smuzhiyun struct most_dev *mdev = usb_get_intfdata(interface);
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
1114*4882a593Smuzhiyun usb_set_intfdata(interface, NULL);
1115*4882a593Smuzhiyun mdev->usb_device = NULL;
1116*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun del_timer_sync(&mdev->link_stat_timer);
1119*4882a593Smuzhiyun cancel_work_sync(&mdev->poll_work_obj);
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun if (mdev->dci)
1122*4882a593Smuzhiyun device_unregister(&mdev->dci->dev);
1123*4882a593Smuzhiyun most_deregister_interface(&mdev->iface);
1124*4882a593Smuzhiyun
1125*4882a593Smuzhiyun kfree(mdev->busy_urbs);
1126*4882a593Smuzhiyun kfree(mdev->cap);
1127*4882a593Smuzhiyun kfree(mdev->conf);
1128*4882a593Smuzhiyun kfree(mdev->ep_address);
1129*4882a593Smuzhiyun put_device(&mdev->dci->dev);
1130*4882a593Smuzhiyun put_device(&mdev->dev);
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun
hdm_suspend(struct usb_interface * interface,pm_message_t message)1133*4882a593Smuzhiyun static int hdm_suspend(struct usb_interface *interface, pm_message_t message)
1134*4882a593Smuzhiyun {
1135*4882a593Smuzhiyun struct most_dev *mdev = usb_get_intfdata(interface);
1136*4882a593Smuzhiyun int i;
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
1139*4882a593Smuzhiyun for (i = 0; i < mdev->iface.num_channels; i++) {
1140*4882a593Smuzhiyun most_stop_enqueue(&mdev->iface, i);
1141*4882a593Smuzhiyun usb_kill_anchored_urbs(&mdev->busy_urbs[i]);
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1144*4882a593Smuzhiyun return 0;
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun
hdm_resume(struct usb_interface * interface)1147*4882a593Smuzhiyun static int hdm_resume(struct usb_interface *interface)
1148*4882a593Smuzhiyun {
1149*4882a593Smuzhiyun struct most_dev *mdev = usb_get_intfdata(interface);
1150*4882a593Smuzhiyun int i;
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun mutex_lock(&mdev->io_mutex);
1153*4882a593Smuzhiyun for (i = 0; i < mdev->iface.num_channels; i++)
1154*4882a593Smuzhiyun most_resume_enqueue(&mdev->iface, i);
1155*4882a593Smuzhiyun mutex_unlock(&mdev->io_mutex);
1156*4882a593Smuzhiyun return 0;
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun static struct usb_driver hdm_usb = {
1160*4882a593Smuzhiyun .name = "hdm_usb",
1161*4882a593Smuzhiyun .id_table = usbid,
1162*4882a593Smuzhiyun .probe = hdm_probe,
1163*4882a593Smuzhiyun .disconnect = hdm_disconnect,
1164*4882a593Smuzhiyun .resume = hdm_resume,
1165*4882a593Smuzhiyun .suspend = hdm_suspend,
1166*4882a593Smuzhiyun };
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun module_usb_driver(hdm_usb);
1169*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1170*4882a593Smuzhiyun MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
1171*4882a593Smuzhiyun MODULE_DESCRIPTION("HDM_4_USB");
1172