Loading drivers/staging/octeon-usb/octeon-hcd.c +111 −243 Original line number Diff line number Diff line Loading @@ -204,48 +204,6 @@ struct cvmx_usb_iso_packet { enum cvmx_usb_complete status; }; /** * enum cvmx_usb_callback - possible callback reasons for the USB API * * @CVMX_USB_CALLBACK_TRANSFER_COMPLETE: A callback of this type is called when * a submitted transfer completes. The * completion callback will be called even * if the transfer fails or is canceled. * The status parameter will contain * details of why he callback was called. * @__CVMX_USB_CALLBACK_END: Do not use. Used internally for array * bounds. */ enum cvmx_usb_callback { CVMX_USB_CALLBACK_TRANSFER_COMPLETE, __CVMX_USB_CALLBACK_END }; struct cvmx_usb_state; /** * USB callback functions are always of the following type. * The parameters are as follows: * - usb = USB device state populated by cvmx_usb_initialize(). * - reason = The enum cvmx_usb_callback used to register * the callback. * - status = The enum cvmx_usb_complete representing the * status code of a transaction. * - pipe_handle = The Pipe that caused this callback, or * -1 if this callback wasn't associated with a pipe. * - submit_handle = Transfer submit handle causing this * callback, or -1 if this callback wasn't associated * with a transfer. * - Actual number of bytes transfer. * - user_data = The user pointer supplied to the * function cvmx_usb_submit(). */ typedef void (*cvmx_usb_callback_func_t)(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data); /** * enum cvmx_usb_initialize_flags - flags used by the initialization function * Loading Loading @@ -376,7 +334,6 @@ enum cvmx_usb_stage { * @iso_packets: For ISO transactions, the sub packets in the request. * @actual_bytes: Actual bytes transfer for this transaction. * @stage: For control transactions, the current stage. * @callback: User's callback function when complete. * @callback_data: User's data. */ struct cvmx_usb_transaction { Loading @@ -395,7 +352,6 @@ struct cvmx_usb_transaction { int retries; int actual_bytes; enum cvmx_usb_stage stage; cvmx_usb_callback_func_t callback; void *callback_data; }; Loading Loading @@ -2173,50 +2129,109 @@ static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof) return; } static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) { return container_of(p, struct octeon_hcd, usb); } /** * Call a user's callback for a specific reason. * * @usb: USB device state populated by cvmx_usb_initialize(). * @pipe: Pipe the callback is for or NULL * @transaction: * Transaction the callback is for or NULL * @reason: Reason this callback is being called * @complete_code: * Completion code for the transaction, if any */ static void __cvmx_usb_perform_callback(struct cvmx_usb_state *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_callback reason, enum cvmx_usb_complete complete_code) static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) { cvmx_usb_callback_func_t callback = NULL; void *user_data; int submit_handle = -1; int pipe_handle = -1; int bytes_transferred = 0; return container_of((void *)p, struct usb_hcd, hcd_priv); } if (pipe) pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); struct usb_hcd *hcd = octeon_to_hcd(priv); struct device *dev = hcd->self.controller; struct urb *urb = user_data; if (transaction) { submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); bytes_transferred = transaction->actual_bytes; /* Transactions are allowed to override the default callback */ if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) { callback = transaction->callback; user_data = transaction->callback_data; } } urb->actual_length = bytes_transferred; urb->hcpriv = NULL; if (!callback) return; if (!list_empty(&urb->urb_list)) { /* * It is on the dequeue_list, but we are going to call * usb_hcd_giveback_urb(), so we must clear it from * the list. We got to it before the * octeon_usb_urb_dequeue_work() tasklet did. */ list_del(&urb->urb_list); /* No longer on the dequeue_list. */ INIT_LIST_HEAD(&urb->urb_list); } callback(usb, reason, complete_code, pipe_handle, submit_handle, bytes_transferred, user_data); /* For Isochronous transactions we need to update the URB packet status list from data in our private copy */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* * The pointer to the private list is stored in the setup_packet * field. */ struct cvmx_usb_iso_packet *iso_packet = (struct cvmx_usb_iso_packet *) urb->setup_packet; /* Recalculate the transfer size by adding up each packet */ urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = iso_packet[i].length; urb->actual_length += urb->iso_frame_desc[i].actual_length; } else { dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n", i, urb->number_of_packets, iso_packet[i].status, pipe_handle, submit_handle, iso_packet[i].length); urb->iso_frame_desc[i].status = -EREMOTEIO; } } /* Free the private list now that we don't need it anymore */ kfree(iso_packet); urb->setup_packet = NULL; } switch (status) { case CVMX_USB_COMPLETE_SUCCESS: urb->status = 0; break; case CVMX_USB_COMPLETE_CANCEL: if (urb->status == 0) urb->status = -ENOENT; break; case CVMX_USB_COMPLETE_STALL: dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_BABBLEERR: dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_SHORT: dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EREMOTEIO; break; case CVMX_USB_COMPLETE_ERROR: case CVMX_USB_COMPLETE_XACTERR: case CVMX_USB_COMPLETE_DATATGLERR: case CVMX_USB_COMPLETE_FRAMEERR: dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n", status, pipe_handle, submit_handle, bytes_transferred); urb->status = -EPROTO; break; } spin_unlock(&priv->lock); usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); spin_lock(&priv->lock); } /** * Signal the completion of a transaction and free it. The Loading @@ -2234,6 +2249,9 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, struct cvmx_usb_transaction *transaction, enum cvmx_usb_complete complete_code) { int pipe_handle; int submit_handle; /* If this was a split then clear our split in progress marker */ if (usb->active_split == transaction) usb->active_split = NULL; Loading Loading @@ -2277,9 +2295,12 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); } __cvmx_usb_perform_callback(usb, pipe, transaction, CVMX_USB_CALLBACK_TRANSFER_COMPLETE, complete_code); pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); octeon_usb_urb_complete_callback(usb, complete_code, pipe_handle, submit_handle, transaction->actual_bytes, transaction->callback_data); __cvmx_usb_free_transaction(usb, transaction); done: return; Loading @@ -2305,7 +2326,6 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, * For ISO, the number of packet in the transaction. * @iso_packets: * A description of each ISO packet * @callback: User callback to call when the transaction completes * @user_data: User's data for the callback * * Returns: Submit handle or negative on failure. Matches the result Loading @@ -2320,7 +2340,6 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, int iso_start_frame, int iso_number_packets, struct cvmx_usb_iso_packet *iso_packets, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2347,7 +2366,6 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, transaction->iso_start_frame = iso_start_frame; transaction->iso_number_packets = iso_number_packets; transaction->iso_packets = iso_packets; transaction->callback = callback; transaction->callback_data = user_data; if (transaction->type == CVMX_USB_TRANSFER_CONTROL) transaction->stage = CVMX_USB_STAGE_SETUP; Loading Loading @@ -2392,23 +2410,14 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2427,7 +2436,6 @@ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading @@ -2446,25 +2454,15 @@ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) int buffer_length, void *user_data) { int submit_handle; Loading @@ -2482,7 +2480,6 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading @@ -2505,16 +2502,8 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. Loading @@ -2522,7 +2511,6 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, int pipe_handle, uint64_t control_header, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2548,7 +2536,6 @@ static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading Loading @@ -2578,16 +2565,8 @@ static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. Loading @@ -2597,7 +2576,6 @@ static int cvmx_usb_submit_isochronous(struct cvmx_usb_state *usb, int number_packets, struct cvmx_usb_iso_packet packets[], uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2622,7 +2600,6 @@ static int cvmx_usb_submit_isochronous(struct cvmx_usb_state *usb, start_frame, number_packets, packets, callback, user_data); return submit_handle; } Loading Loading @@ -3217,16 +3194,6 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) return 0; } static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) { return container_of(p, struct octeon_hcd, usb); } static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) { return container_of((void *)p, struct usb_hcd, hcd_priv); } static void octeon_usb_port_callback(struct cvmx_usb_state *usb) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); Loading Loading @@ -3372,101 +3339,6 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd) return cvmx_usb_get_frame_number(&priv->usb); } static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); struct usb_hcd *hcd = octeon_to_hcd(priv); struct device *dev = hcd->self.controller; struct urb *urb = user_data; urb->actual_length = bytes_transferred; urb->hcpriv = NULL; if (!list_empty(&urb->urb_list)) { /* * It is on the dequeue_list, but we are going to call * usb_hcd_giveback_urb(), so we must clear it from * the list. We got to it before the * octeon_usb_urb_dequeue_work() tasklet did. */ list_del(&urb->urb_list); /* No longer on the dequeue_list. */ INIT_LIST_HEAD(&urb->urb_list); } /* For Isochronous transactions we need to update the URB packet status list from data in our private copy */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* * The pointer to the private list is stored in the setup_packet * field. */ struct cvmx_usb_iso_packet *iso_packet = (struct cvmx_usb_iso_packet *) urb->setup_packet; /* Recalculate the transfer size by adding up each packet */ urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = iso_packet[i].length; urb->actual_length += urb->iso_frame_desc[i].actual_length; } else { dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n", i, urb->number_of_packets, iso_packet[i].status, pipe_handle, submit_handle, iso_packet[i].length); urb->iso_frame_desc[i].status = -EREMOTEIO; } } /* Free the private list now that we don't need it anymore */ kfree(iso_packet); urb->setup_packet = NULL; } switch (status) { case CVMX_USB_COMPLETE_SUCCESS: urb->status = 0; break; case CVMX_USB_COMPLETE_CANCEL: if (urb->status == 0) urb->status = -ENOENT; break; case CVMX_USB_COMPLETE_STALL: dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_BABBLEERR: dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_SHORT: dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EREMOTEIO; break; case CVMX_USB_COMPLETE_ERROR: case CVMX_USB_COMPLETE_XACTERR: case CVMX_USB_COMPLETE_DATATGLERR: case CVMX_USB_COMPLETE_FRAMEERR: dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n", status, pipe_handle, submit_handle, bytes_transferred); urb->status = -EPROTO; break; } spin_unlock(&priv->lock); usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); spin_lock(&priv->lock); } static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) Loading Loading @@ -3595,7 +3467,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, iso_packet, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); /* * If submit failed we need to free our private packet Loading @@ -3613,7 +3484,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; case PIPE_CONTROL: Loading @@ -3623,7 +3493,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, urb->setup_dma, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; case PIPE_BULK: Loading @@ -3632,7 +3501,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; } Loading Loading
drivers/staging/octeon-usb/octeon-hcd.c +111 −243 Original line number Diff line number Diff line Loading @@ -204,48 +204,6 @@ struct cvmx_usb_iso_packet { enum cvmx_usb_complete status; }; /** * enum cvmx_usb_callback - possible callback reasons for the USB API * * @CVMX_USB_CALLBACK_TRANSFER_COMPLETE: A callback of this type is called when * a submitted transfer completes. The * completion callback will be called even * if the transfer fails or is canceled. * The status parameter will contain * details of why he callback was called. * @__CVMX_USB_CALLBACK_END: Do not use. Used internally for array * bounds. */ enum cvmx_usb_callback { CVMX_USB_CALLBACK_TRANSFER_COMPLETE, __CVMX_USB_CALLBACK_END }; struct cvmx_usb_state; /** * USB callback functions are always of the following type. * The parameters are as follows: * - usb = USB device state populated by cvmx_usb_initialize(). * - reason = The enum cvmx_usb_callback used to register * the callback. * - status = The enum cvmx_usb_complete representing the * status code of a transaction. * - pipe_handle = The Pipe that caused this callback, or * -1 if this callback wasn't associated with a pipe. * - submit_handle = Transfer submit handle causing this * callback, or -1 if this callback wasn't associated * with a transfer. * - Actual number of bytes transfer. * - user_data = The user pointer supplied to the * function cvmx_usb_submit(). */ typedef void (*cvmx_usb_callback_func_t)(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data); /** * enum cvmx_usb_initialize_flags - flags used by the initialization function * Loading Loading @@ -376,7 +334,6 @@ enum cvmx_usb_stage { * @iso_packets: For ISO transactions, the sub packets in the request. * @actual_bytes: Actual bytes transfer for this transaction. * @stage: For control transactions, the current stage. * @callback: User's callback function when complete. * @callback_data: User's data. */ struct cvmx_usb_transaction { Loading @@ -395,7 +352,6 @@ struct cvmx_usb_transaction { int retries; int actual_bytes; enum cvmx_usb_stage stage; cvmx_usb_callback_func_t callback; void *callback_data; }; Loading Loading @@ -2173,50 +2129,109 @@ static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof) return; } static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) { return container_of(p, struct octeon_hcd, usb); } /** * Call a user's callback for a specific reason. * * @usb: USB device state populated by cvmx_usb_initialize(). * @pipe: Pipe the callback is for or NULL * @transaction: * Transaction the callback is for or NULL * @reason: Reason this callback is being called * @complete_code: * Completion code for the transaction, if any */ static void __cvmx_usb_perform_callback(struct cvmx_usb_state *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_callback reason, enum cvmx_usb_complete complete_code) static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) { cvmx_usb_callback_func_t callback = NULL; void *user_data; int submit_handle = -1; int pipe_handle = -1; int bytes_transferred = 0; return container_of((void *)p, struct usb_hcd, hcd_priv); } if (pipe) pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); struct usb_hcd *hcd = octeon_to_hcd(priv); struct device *dev = hcd->self.controller; struct urb *urb = user_data; if (transaction) { submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); bytes_transferred = transaction->actual_bytes; /* Transactions are allowed to override the default callback */ if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) { callback = transaction->callback; user_data = transaction->callback_data; } } urb->actual_length = bytes_transferred; urb->hcpriv = NULL; if (!callback) return; if (!list_empty(&urb->urb_list)) { /* * It is on the dequeue_list, but we are going to call * usb_hcd_giveback_urb(), so we must clear it from * the list. We got to it before the * octeon_usb_urb_dequeue_work() tasklet did. */ list_del(&urb->urb_list); /* No longer on the dequeue_list. */ INIT_LIST_HEAD(&urb->urb_list); } callback(usb, reason, complete_code, pipe_handle, submit_handle, bytes_transferred, user_data); /* For Isochronous transactions we need to update the URB packet status list from data in our private copy */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* * The pointer to the private list is stored in the setup_packet * field. */ struct cvmx_usb_iso_packet *iso_packet = (struct cvmx_usb_iso_packet *) urb->setup_packet; /* Recalculate the transfer size by adding up each packet */ urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = iso_packet[i].length; urb->actual_length += urb->iso_frame_desc[i].actual_length; } else { dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n", i, urb->number_of_packets, iso_packet[i].status, pipe_handle, submit_handle, iso_packet[i].length); urb->iso_frame_desc[i].status = -EREMOTEIO; } } /* Free the private list now that we don't need it anymore */ kfree(iso_packet); urb->setup_packet = NULL; } switch (status) { case CVMX_USB_COMPLETE_SUCCESS: urb->status = 0; break; case CVMX_USB_COMPLETE_CANCEL: if (urb->status == 0) urb->status = -ENOENT; break; case CVMX_USB_COMPLETE_STALL: dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_BABBLEERR: dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_SHORT: dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EREMOTEIO; break; case CVMX_USB_COMPLETE_ERROR: case CVMX_USB_COMPLETE_XACTERR: case CVMX_USB_COMPLETE_DATATGLERR: case CVMX_USB_COMPLETE_FRAMEERR: dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n", status, pipe_handle, submit_handle, bytes_transferred); urb->status = -EPROTO; break; } spin_unlock(&priv->lock); usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); spin_lock(&priv->lock); } /** * Signal the completion of a transaction and free it. The Loading @@ -2234,6 +2249,9 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, struct cvmx_usb_transaction *transaction, enum cvmx_usb_complete complete_code) { int pipe_handle; int submit_handle; /* If this was a split then clear our split in progress marker */ if (usb->active_split == transaction) usb->active_split = NULL; Loading Loading @@ -2277,9 +2295,12 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); } __cvmx_usb_perform_callback(usb, pipe, transaction, CVMX_USB_CALLBACK_TRANSFER_COMPLETE, complete_code); pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); octeon_usb_urb_complete_callback(usb, complete_code, pipe_handle, submit_handle, transaction->actual_bytes, transaction->callback_data); __cvmx_usb_free_transaction(usb, transaction); done: return; Loading @@ -2305,7 +2326,6 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, * For ISO, the number of packet in the transaction. * @iso_packets: * A description of each ISO packet * @callback: User callback to call when the transaction completes * @user_data: User's data for the callback * * Returns: Submit handle or negative on failure. Matches the result Loading @@ -2320,7 +2340,6 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, int iso_start_frame, int iso_number_packets, struct cvmx_usb_iso_packet *iso_packets, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2347,7 +2366,6 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, transaction->iso_start_frame = iso_start_frame; transaction->iso_number_packets = iso_number_packets; transaction->iso_packets = iso_packets; transaction->callback = callback; transaction->callback_data = user_data; if (transaction->type == CVMX_USB_TRANSFER_CONTROL) transaction->stage = CVMX_USB_STAGE_SETUP; Loading Loading @@ -2392,23 +2410,14 @@ static int __cvmx_usb_submit_transaction(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2427,7 +2436,6 @@ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading @@ -2446,25 +2454,15 @@ static int cvmx_usb_submit_bulk(struct cvmx_usb_state *usb, int pipe_handle, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) int buffer_length, void *user_data) { int submit_handle; Loading @@ -2482,7 +2480,6 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading @@ -2505,16 +2502,8 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. Loading @@ -2522,7 +2511,6 @@ static int cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb, static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, int pipe_handle, uint64_t control_header, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2548,7 +2536,6 @@ static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, 0, /* iso_start_frame */ 0, /* iso_number_packets */ NULL, /* iso_packets */ callback, user_data); return submit_handle; } Loading Loading @@ -2578,16 +2565,8 @@ static int cvmx_usb_submit_control(struct cvmx_usb_state *usb, * zero. * @buffer_length: * Length of buffer in bytes. * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the * transaction completes. If this parameter is * NULL, then there is no way to know when a transaction * completes. * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * callback is called. * * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. Loading @@ -2597,7 +2576,6 @@ static int cvmx_usb_submit_isochronous(struct cvmx_usb_state *usb, int number_packets, struct cvmx_usb_iso_packet packets[], uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) { int submit_handle; Loading @@ -2622,7 +2600,6 @@ static int cvmx_usb_submit_isochronous(struct cvmx_usb_state *usb, start_frame, number_packets, packets, callback, user_data); return submit_handle; } Loading Loading @@ -3217,16 +3194,6 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) return 0; } static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) { return container_of(p, struct octeon_hcd, usb); } static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) { return container_of((void *)p, struct usb_hcd, hcd_priv); } static void octeon_usb_port_callback(struct cvmx_usb_state *usb) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); Loading Loading @@ -3372,101 +3339,6 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd) return cvmx_usb_get_frame_number(&priv->usb); } static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data) { struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); struct usb_hcd *hcd = octeon_to_hcd(priv); struct device *dev = hcd->self.controller; struct urb *urb = user_data; urb->actual_length = bytes_transferred; urb->hcpriv = NULL; if (!list_empty(&urb->urb_list)) { /* * It is on the dequeue_list, but we are going to call * usb_hcd_giveback_urb(), so we must clear it from * the list. We got to it before the * octeon_usb_urb_dequeue_work() tasklet did. */ list_del(&urb->urb_list); /* No longer on the dequeue_list. */ INIT_LIST_HEAD(&urb->urb_list); } /* For Isochronous transactions we need to update the URB packet status list from data in our private copy */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* * The pointer to the private list is stored in the setup_packet * field. */ struct cvmx_usb_iso_packet *iso_packet = (struct cvmx_usb_iso_packet *) urb->setup_packet; /* Recalculate the transfer size by adding up each packet */ urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = iso_packet[i].length; urb->actual_length += urb->iso_frame_desc[i].actual_length; } else { dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n", i, urb->number_of_packets, iso_packet[i].status, pipe_handle, submit_handle, iso_packet[i].length); urb->iso_frame_desc[i].status = -EREMOTEIO; } } /* Free the private list now that we don't need it anymore */ kfree(iso_packet); urb->setup_packet = NULL; } switch (status) { case CVMX_USB_COMPLETE_SUCCESS: urb->status = 0; break; case CVMX_USB_COMPLETE_CANCEL: if (urb->status == 0) urb->status = -ENOENT; break; case CVMX_USB_COMPLETE_STALL: dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_BABBLEERR: dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EPIPE; break; case CVMX_USB_COMPLETE_SHORT: dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n", pipe_handle, submit_handle, bytes_transferred); urb->status = -EREMOTEIO; break; case CVMX_USB_COMPLETE_ERROR: case CVMX_USB_COMPLETE_XACTERR: case CVMX_USB_COMPLETE_DATATGLERR: case CVMX_USB_COMPLETE_FRAMEERR: dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n", status, pipe_handle, submit_handle, bytes_transferred); urb->status = -EPROTO; break; } spin_unlock(&priv->lock); usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); spin_lock(&priv->lock); } static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) Loading Loading @@ -3595,7 +3467,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, iso_packet, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); /* * If submit failed we need to free our private packet Loading @@ -3613,7 +3484,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; case PIPE_CONTROL: Loading @@ -3623,7 +3493,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, urb->setup_dma, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; case PIPE_BULK: Loading @@ -3632,7 +3501,6 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle, urb->transfer_dma, urb->transfer_buffer_length, octeon_usb_urb_complete_callback, urb); break; } Loading