]> Pileus Git - ~andy/linux/commitdiff
staging: octeon-usb: use list.h for transactions
authorAaro Koskinen <aaro.koskinen@iki.fi>
Thu, 10 Oct 2013 20:25:36 +0000 (23:25 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Oct 2013 22:46:00 +0000 (15:46 -0700)
Use list.h helpers for transactions.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/octeon-usb/octeon-hcd.c

index 36e4ee46cb44792e0e661808fc08d546d5698d47..d118952c0a74c9ff7d59597ccf76e5a16a4bd60d 100644 (file)
@@ -306,8 +306,7 @@ enum cvmx_usb_stage {
  *                              regardless of type. These are linked together
  *                              to form a list of pending requests for a pipe.
  *
- * @prev:              Transaction before this one in the pipe.
- * @next:              Transaction after this one in the pipe.
+ * @node:              List node for transactions in the pipe.
  * @type:              Type of transaction, duplicated of the pipe.
  * @flags:             State flags for this transaction.
  * @buffer:            User's physical buffer address to read/write.
@@ -323,8 +322,7 @@ enum cvmx_usb_stage {
  * @urb:               URB.
  */
 struct cvmx_usb_transaction {
-       struct cvmx_usb_transaction *prev;
-       struct cvmx_usb_transaction *next;
+       struct list_head node;
        enum cvmx_usb_transfer type;
        uint64_t buffer;
        int buffer_length;
@@ -347,8 +345,7 @@ struct cvmx_usb_transaction {
  *
  * @node:              List node for pipe list
  * @next:              Pipe after this one in the list
- * @head:              The first pending transaction
- * @tail:              The last pending transaction
+ * @transactions:      List of pending transactions
  * @interval:          For periodic pipes, the interval between packets in
  *                     frames
  * @next_tx_frame:     The next frame this pipe is allowed to transmit on
@@ -370,8 +367,7 @@ struct cvmx_usb_transaction {
  */
 struct cvmx_usb_pipe {
        struct list_head node;
-       struct cvmx_usb_transaction *head;
-       struct cvmx_usb_transaction *tail;
+       struct list_head transactions;
        uint64_t interval;
        uint64_t next_tx_frame;
        enum cvmx_usb_pipe_flags flags;
@@ -1219,6 +1215,8 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb,
        pipe->max_packet = max_packet;
        pipe->transfer_type = transfer_type;
        pipe->transfer_dir = transfer_dir;
+       INIT_LIST_HEAD(&pipe->transactions);
+
        /*
         * All pipes use interval to rate limit NAK processing. Force an
         * interval if one wasn't supplied
@@ -1444,7 +1442,9 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
                                             int channel,
                                             struct cvmx_usb_pipe *pipe)
 {
-       struct cvmx_usb_transaction *transaction = pipe->head;
+       struct cvmx_usb_transaction *transaction =
+               list_first_entry(&pipe->transactions, typeof(*transaction),
+                                node);
        union cvmx_usb_control_header *header =
                cvmx_phys_to_ptr(transaction->control_header);
        int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
@@ -1573,7 +1573,9 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                                     int channel,
                                     struct cvmx_usb_pipe *pipe)
 {
-       struct cvmx_usb_transaction *transaction = pipe->head;
+       struct cvmx_usb_transaction *transaction =
+               list_first_entry(&pipe->transactions, typeof(*transaction),
+                                node);
 
        /* Make sure all writes to the DMA region get flushed */
        CVMX_SYNCW;
@@ -1872,12 +1874,14 @@ static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_state *u
        struct cvmx_usb_pipe *pipe;
 
        list_for_each_entry(pipe, list, node) {
-               if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head &&
+               struct cvmx_usb_transaction *t =
+                       list_first_entry(&pipe->transactions, typeof(*t), node);
+               if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && t &&
                        (pipe->next_tx_frame <= current_frame) &&
                        ((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) &&
-                       (!usb->active_split || (usb->active_split == pipe->head))) {
+                       (!usb->active_split || (usb->active_split == t))) {
                        CVMX_PREFETCH(pipe, 128);
-                       CVMX_PREFETCH(pipe->head, 0);
+                       CVMX_PREFETCH(t, 0);
                        return pipe;
                }
        }
@@ -2104,15 +2108,8 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb,
        }
 
        /* Remove the transaction from the pipe list */
-       if (transaction->next)
-               transaction->next->prev = transaction->prev;
-       else
-               pipe->tail = transaction->prev;
-       if (transaction->prev)
-               transaction->prev->next = transaction->next;
-       else
-               pipe->head = transaction->next;
-       if (!pipe->head)
+       list_del(&transaction->node);
+       if (list_empty(&pipe->transactions))
                list_move_tail(&pipe->node, &usb->idle_pipes);
        octeon_usb_urb_complete_callback(usb, complete_code, pipe,
                                         transaction,
@@ -2180,24 +2177,19 @@ static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(struct cvmx_us
        else
                transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
 
-       transaction->next = NULL;
-       if (pipe->tail) {
-               transaction->prev = pipe->tail;
-               transaction->prev->next = transaction;
+       if (!list_empty(&pipe->transactions)) {
+               list_add_tail(&transaction->node, &pipe->transactions);
        } else {
-               if (pipe->next_tx_frame < usb->frame_number)
-                       pipe->next_tx_frame = usb->frame_number + pipe->interval -
-                               (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-               transaction->prev = NULL;
-               pipe->head = transaction;
+               list_add_tail(&transaction->node, &pipe->transactions);
                list_move_tail(&pipe->node,
                               &usb->active_pipes[pipe->transfer_type]);
-       }
-       pipe->tail = transaction;
 
-       /* We may need to schedule the pipe if this was the head of the pipe */
-       if (!transaction->prev)
+               /*
+                * We may need to schedule the pipe if this was the head of the
+                * pipe.
+                */
                __cvmx_usb_schedule(usb, 0);
+       }
 
        return transaction;
 }
@@ -2332,8 +2324,8 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb,
         * If the transaction is the HEAD of the queue and scheduled. We need to
         * treat it special
         */
-       if ((pipe->head == transaction) &&
-               (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
+       if (list_first_entry(&pipe->transactions, typeof(*transaction), node) ==
+           transaction && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
                union cvmx_usbcx_hccharx usbc_hcchar;
 
                usb->pipe_for_channel[pipe->channel] = NULL;
@@ -2368,9 +2360,11 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb,
 static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb,
                               struct cvmx_usb_pipe *pipe)
 {
+       struct cvmx_usb_transaction *transaction, *next;
+
        /* Simply loop through and attempt to cancel each transaction */
-       while (pipe->head) {
-               int result = cvmx_usb_cancel(usb, pipe, pipe->head);
+       list_for_each_entry_safe(transaction, next, &pipe->transactions, node) {
+               int result = cvmx_usb_cancel(usb, pipe, transaction);
                if (unlikely(result != 0))
                        return result;
        }
@@ -2391,7 +2385,7 @@ static int cvmx_usb_close_pipe(struct cvmx_usb_state *usb,
                               struct cvmx_usb_pipe *pipe)
 {
        /* Fail if the pipe has pending transactions */
-       if (unlikely(pipe->head))
+       if (!list_empty(&pipe->transactions))
                return -EBUSY;
 
        list_del(&pipe->node);
@@ -2499,7 +2493,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
        CVMX_PREFETCH(pipe, 128);
        if (!pipe)
                return 0;
-       transaction = pipe->head;
+       transaction = list_first_entry(&pipe->transactions, typeof(*transaction),
+                                      node);
        CVMX_PREFETCH(transaction, 0);
 
        /*