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