]> Pileus Git - ~andy/linux/blob - drivers/staging/bcm/InterfaceMisc.c
Staging: bcm: Remove null dereference from InterfaceRDM.
[~andy/linux] / drivers / staging / bcm / InterfaceMisc.c
1 #include "headers.h"
2
3 int InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
4                 unsigned int addr,
5                 void *buff,
6                 int len)
7 {
8         int bytes;
9
10         if (!psIntfAdapter)
11                 return -EINVAL;
12
13         if (psIntfAdapter->psAdapter->device_removed == TRUE) {
14                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
15                 return -ENODEV;
16         }
17
18         if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
19                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
20                 return -EACCES;
21         }
22
23         if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
24                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
25                 return -EACCES;
26         }
27         psIntfAdapter->psAdapter->DeviceAccess = TRUE;
28
29         bytes = usb_control_msg(psIntfAdapter->udev,
30                                 usb_rcvctrlpipe(psIntfAdapter->udev, 0),
31                                 0x02,
32                                 0xC2,
33                                 (addr & 0xFFFF),
34                                 ((addr >> 16) & 0xFFFF),
35                                 buff,
36                                 len,
37                                 5000);
38
39         if (-ENODEV == bytes)
40                 psIntfAdapter->psAdapter->device_removed = TRUE;
41
42         if (bytes < 0)
43                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes);
44         else
45                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
46
47         psIntfAdapter->psAdapter->DeviceAccess = FALSE;
48         return bytes;
49 }
50
51 int InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
52                 unsigned int addr,
53                 void *buff,
54                 int len)
55 {
56         int retval = 0;
57
58         if (!psIntfAdapter) {
59                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter  is NULL");
60                 return -EINVAL;
61         }
62
63         if (psIntfAdapter->psAdapter->device_removed == TRUE) {
64                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
65                 return -ENODEV;
66         }
67
68         if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
69                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
70                 return -EACCES;
71         }
72
73         if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
74                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
75                 return -EACCES;
76         }
77
78         psIntfAdapter->psAdapter->DeviceAccess = TRUE;
79
80         retval = usb_control_msg(psIntfAdapter->udev,
81                                 usb_sndctrlpipe(psIntfAdapter->udev, 0),
82                                 0x01,
83                                 0x42,
84                                 (addr & 0xFFFF),
85                                 ((addr >> 16) & 0xFFFF),
86                                 buff,
87                                 len,
88                                 5000);
89
90         if (-ENODEV == retval)
91                 psIntfAdapter->psAdapter->device_removed = TRUE;
92
93         if (retval < 0) {
94                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
95                 psIntfAdapter->psAdapter->DeviceAccess = FALSE;
96                 return retval;
97         } else {
98                 psIntfAdapter->psAdapter->DeviceAccess = FALSE;
99                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
100                 return STATUS_SUCCESS;
101         }
102 }
103
104 int BcmRDM(void *arg,
105         unsigned int addr,
106         void *buff,
107         int len)
108 {
109         return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
110 }
111
112 int BcmWRM(void *arg,
113         unsigned int addr,
114         void *buff,
115         int len)
116 {
117         return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
118 }
119
120 int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
121 {
122         PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
123         int status = STATUS_SUCCESS;
124
125         /*
126          * usb_clear_halt - tells device to clear endpoint halt/stall condition
127          * @dev: device whose endpoint is halted
128          * @pipe: endpoint "pipe" being cleared
129          * @ Context: !in_interrupt ()
130          *
131          * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
132          * This is used to clear halt conditions for bulk and interrupt endpoints only.
133          * Control and isochronous endpoints never halts.
134          *
135          * Any URBs  queued for such an endpoint should normally be unlinked by the driver
136          * before clearing the halt condition.
137          *
138          */
139
140         /* Killing all the submitted urbs to different end points. */
141         Bcm_kill_all_URBs(psIntfAdapter);
142
143         /* clear the halted/stalled state for every end point */
144         status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
145         if (status != STATUS_SUCCESS)
146                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
147
148         status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe);
149         if (status != STATUS_SUCCESS)
150                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
151
152         status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe);
153         if (status != STATUS_SUCCESS)
154                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
155
156         return status;
157 }
158
159 void Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
160 {
161         struct urb *tempUrb = NULL;
162         unsigned int i;
163
164         /*
165          * usb_kill_urb - cancel a transfer request and wait for it to finish
166          * @urb: pointer to URB describing a previously submitted request,
167          * returns nothing as it is void returned API.
168          *
169          * This routine cancels an in-progress request. It is guaranteed that
170          * upon return all completion handlers will have finished and the URB
171          * will be totally idle and available for reuse
172          *
173          * This routine may not be used in an interrupt context (such as a bottom
174          * half or a completion handler), or when holding a spinlock, or in other
175          * situations where the caller can't schedule().
176          *
177          */
178
179         /* Cancel submitted Interrupt-URB's */
180         if (psIntfAdapter->psInterruptUrb) {
181                 if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
182                         usb_kill_urb(psIntfAdapter->psInterruptUrb);
183         }
184
185         /* Cancel All submitted TX URB's */
186         for (i = 0; i < MAXIMUM_USB_TCB; i++) {
187                 tempUrb = psIntfAdapter->asUsbTcb[i].urb;
188                 if (tempUrb) {
189                         if (tempUrb->status == -EINPROGRESS)
190                                 usb_kill_urb(tempUrb);
191                 }
192         }
193
194         for (i = 0; i < MAXIMUM_USB_RCB; i++) {
195                 tempUrb = psIntfAdapter->asUsbRcb[i].urb;
196                 if (tempUrb) {
197                         if (tempUrb->status == -EINPROGRESS)
198                                 usb_kill_urb(tempUrb);
199                 }
200         }
201
202         atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
203         atomic_set(&psIntfAdapter->uCurrTcb, 0);
204
205         atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
206         atomic_set(&psIntfAdapter->uCurrRcb, 0);
207 }
208
209 void putUsbSuspend(struct work_struct *work)
210 {
211         PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
212         struct usb_interface *intf = NULL;
213         psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
214         intf = psIntfAdapter->interface;
215
216         if (psIntfAdapter->bSuspended == FALSE)
217                 usb_autopm_put_interface(intf);
218 }
219