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