aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/ieee1394_transactions.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/ieee1394_transactions.c')
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c108
1 files changed, 63 insertions, 45 deletions
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 751960037e27..0833fc9f50c4 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -9,10 +9,9 @@
9 * directory of the kernel sources for details. 9 * directory of the kernel sources for details.
10 */ 10 */
11 11
12#include <linux/sched.h>
13#include <linux/bitops.h> 12#include <linux/bitops.h>
14#include <linux/smp_lock.h> 13#include <linux/spinlock.h>
15#include <linux/interrupt.h> 14#include <linux/wait.h>
16 15
17#include <asm/bug.h> 16#include <asm/bug.h>
18#include <asm/errno.h> 17#include <asm/errno.h>
@@ -21,8 +20,6 @@
21#include "ieee1394_types.h" 20#include "ieee1394_types.h"
22#include "hosts.h" 21#include "hosts.h"
23#include "ieee1394_core.h" 22#include "ieee1394_core.h"
24#include "highlevel.h"
25#include "nodemgr.h"
26#include "ieee1394_transactions.h" 23#include "ieee1394_transactions.h"
27 24
28#define PREP_ASYNC_HEAD_ADDRESS(tc) \ 25#define PREP_ASYNC_HEAD_ADDRESS(tc) \
@@ -32,6 +29,13 @@
32 packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ 29 packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
33 packet->header[2] = addr & 0xffffffff 30 packet->header[2] = addr & 0xffffffff
34 31
32#ifndef HPSB_DEBUG_TLABELS
33static
34#endif
35spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED;
36
37static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
38
35static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) 39static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
36{ 40{
37 PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); 41 PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
@@ -115,9 +119,41 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
115 packet->tcode = TCODE_ISO_DATA; 119 packet->tcode = TCODE_ISO_DATA;
116} 120}
117 121
122/* same as hpsb_get_tlabel, except that it returns immediately */
123static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
124{
125 unsigned long flags, *tp;
126 u8 *next;
127 int tlabel, n = NODEID_TO_NODE(packet->node_id);
128
129 /* Broadcast transactions are complete once the request has been sent.
130 * Use the same transaction label for all broadcast transactions. */
131 if (unlikely(n == ALL_NODES)) {
132 packet->tlabel = 0;
133 return 0;
134 }
135 tp = packet->host->tl_pool[n].map;
136 next = &packet->host->next_tl[n];
137
138 spin_lock_irqsave(&hpsb_tlabel_lock, flags);
139 tlabel = find_next_zero_bit(tp, 64, *next);
140 if (tlabel > 63)
141 tlabel = find_first_zero_bit(tp, 64);
142 if (tlabel > 63) {
143 spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
144 return -EAGAIN;
145 }
146 __set_bit(tlabel, tp);
147 *next = (tlabel + 1) & 63;
148 spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
149
150 packet->tlabel = tlabel;
151 return 0;
152}
153
118/** 154/**
119 * hpsb_get_tlabel - allocate a transaction label 155 * hpsb_get_tlabel - allocate a transaction label
120 * @packet: the packet who's tlabel/tpool we set 156 * @packet: the packet whose tlabel and tl_pool we set
121 * 157 *
122 * Every asynchronous transaction on the 1394 bus needs a transaction 158 * Every asynchronous transaction on the 1394 bus needs a transaction
123 * label to match the response to the request. This label has to be 159 * label to match the response to the request. This label has to be
@@ -131,42 +167,25 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
131 * Return value: Zero on success, otherwise non-zero. A non-zero return 167 * Return value: Zero on success, otherwise non-zero. A non-zero return
132 * generally means there are no available tlabels. If this is called out 168 * generally means there are no available tlabels. If this is called out
133 * of interrupt or atomic context, then it will sleep until can return a 169 * of interrupt or atomic context, then it will sleep until can return a
134 * tlabel. 170 * tlabel or a signal is received.
135 */ 171 */
136int hpsb_get_tlabel(struct hpsb_packet *packet) 172int hpsb_get_tlabel(struct hpsb_packet *packet)
137{ 173{
138 unsigned long flags; 174 if (irqs_disabled() || in_atomic())
139 struct hpsb_tlabel_pool *tp; 175 return hpsb_get_tlabel_atomic(packet);
140 int n = NODEID_TO_NODE(packet->node_id); 176
141 177 /* NB: The macro wait_event_interruptible() is called with a condition
142 if (unlikely(n == ALL_NODES)) 178 * argument with side effect. This is only possible because the side
143 return 0; 179 * effect does not occur until the condition became true, and
144 tp = &packet->host->tpool[n]; 180 * wait_event_interruptible() won't evaluate the condition again after
145 181 * that. */
146 if (irqs_disabled() || in_atomic()) { 182 return wait_event_interruptible(tlabel_wq,
147 if (down_trylock(&tp->count)) 183 !hpsb_get_tlabel_atomic(packet));
148 return 1;
149 } else {
150 down(&tp->count);
151 }
152
153 spin_lock_irqsave(&tp->lock, flags);
154
155 packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
156 if (packet->tlabel > 63)
157 packet->tlabel = find_first_zero_bit(tp->pool, 64);
158 tp->next = (packet->tlabel + 1) % 64;
159 /* Should _never_ happen */
160 BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
161 tp->allocations++;
162 spin_unlock_irqrestore(&tp->lock, flags);
163
164 return 0;
165} 184}
166 185
167/** 186/**
168 * hpsb_free_tlabel - free an allocated transaction label 187 * hpsb_free_tlabel - free an allocated transaction label
169 * @packet: packet whos tlabel/tpool needs to be cleared 188 * @packet: packet whose tlabel and tl_pool needs to be cleared
170 * 189 *
171 * Frees the transaction label allocated with hpsb_get_tlabel(). The 190 * Frees the transaction label allocated with hpsb_get_tlabel(). The
172 * tlabel has to be freed after the transaction is complete (i.e. response 191 * tlabel has to be freed after the transaction is complete (i.e. response
@@ -177,21 +196,20 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
177 */ 196 */
178void hpsb_free_tlabel(struct hpsb_packet *packet) 197void hpsb_free_tlabel(struct hpsb_packet *packet)
179{ 198{
180 unsigned long flags; 199 unsigned long flags, *tp;
181 struct hpsb_tlabel_pool *tp; 200 int tlabel, n = NODEID_TO_NODE(packet->node_id);
182 int n = NODEID_TO_NODE(packet->node_id);
183 201
184 if (unlikely(n == ALL_NODES)) 202 if (unlikely(n == ALL_NODES))
185 return; 203 return;
186 tp = &packet->host->tpool[n]; 204 tp = packet->host->tl_pool[n].map;
187 205 tlabel = packet->tlabel;
188 BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); 206 BUG_ON(tlabel > 63 || tlabel < 0);
189 207
190 spin_lock_irqsave(&tp->lock, flags); 208 spin_lock_irqsave(&hpsb_tlabel_lock, flags);
191 BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool)); 209 BUG_ON(!__test_and_clear_bit(tlabel, tp));
192 spin_unlock_irqrestore(&tp->lock, flags); 210 spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
193 211
194 up(&tp->count); 212 wake_up_interruptible(&tlabel_wq);
195} 213}
196 214
197int hpsb_packet_success(struct hpsb_packet *packet) 215int hpsb_packet_success(struct hpsb_packet *packet)