aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ieee1394/hosts.c3
-rw-r--r--drivers/ieee1394/hosts.h19
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c108
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h4
-rw-r--r--drivers/ieee1394/ieee1394_types.h23
-rw-r--r--drivers/ieee1394/nodemgr.c43
-rw-r--r--drivers/ieee1394/nodemgr.h1
7 files changed, 102 insertions, 99 deletions
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 59e6f49545bf..d90a3a1898c0 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -143,9 +143,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
143 for (i = 2; i < 16; i++) 143 for (i = 2; i < 16; i++)
144 h->csr.gen_timestamp[i] = jiffies - 60 * HZ; 144 h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
145 145
146 for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
147 HPSB_TPOOL_INIT(&h->tpool[i]);
148
149 atomic_set(&h->generation, 0); 146 atomic_set(&h->generation, 0);
150 147
151 INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); 148 INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index 69a7c9ff5ed7..bc6dbfadb891 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -35,7 +35,6 @@ struct hpsb_host {
35 int node_count; /* number of identified nodes on this bus */ 35 int node_count; /* number of identified nodes on this bus */
36 int selfid_count; /* total number of SelfIDs received */ 36 int selfid_count; /* total number of SelfIDs received */
37 int nodes_active; /* number of nodes with active link layer */ 37 int nodes_active; /* number of nodes with active link layer */
38 u8 speed[ALL_NODES]; /* speed between each node and local node */
39 38
40 nodeid_t node_id; /* node ID of this host */ 39 nodeid_t node_id; /* node ID of this host */
41 nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ 40 nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
@@ -55,31 +54,29 @@ struct hpsb_host {
55 int reset_retries; 54 int reset_retries;
56 quadlet_t *topology_map; 55 quadlet_t *topology_map;
57 u8 *speed_map; 56 u8 *speed_map;
58 struct csr_control csr;
59
60 /* Per node tlabel pool allocation */
61 struct hpsb_tlabel_pool tpool[ALL_NODES];
62 57
58 int id;
63 struct hpsb_host_driver *driver; 59 struct hpsb_host_driver *driver;
64
65 struct pci_dev *pdev; 60 struct pci_dev *pdev;
66
67 int id;
68
69 struct device device; 61 struct device device;
70 struct class_device class_dev; 62 struct class_device class_dev;
71 63
72 int update_config_rom; 64 int update_config_rom;
73 struct work_struct delayed_reset; 65 struct work_struct delayed_reset;
74
75 unsigned int config_roms; 66 unsigned int config_roms;
76 67
77 struct list_head addr_space; 68 struct list_head addr_space;
78 u64 low_addr_space; /* upper bound of physical DMA area */ 69 u64 low_addr_space; /* upper bound of physical DMA area */
79 u64 middle_addr_space; /* upper bound of posted write area */ 70 u64 middle_addr_space; /* upper bound of posted write area */
80};
81 71
72 u8 speed[ALL_NODES]; /* speed between each node and local node */
82 73
74 /* per node tlabel allocation */
75 u8 next_tl[ALL_NODES];
76 struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
77
78 struct csr_control csr;
79};
83 80
84enum devctl_cmd { 81enum devctl_cmd {
85 /* Host is requested to reset its bus and cancel all outstanding async 82 /* Host is requested to reset its bus and cancel all outstanding async
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)
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 290d37060b03..c1369c41469b 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -53,4 +53,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
53int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, 53int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
54 u64 addr, quadlet_t *buffer, size_t length); 54 u64 addr, quadlet_t *buffer, size_t length);
55 55
56#ifdef HPSB_DEBUG_TLABELS
57extern spinlock_t hpsb_tlabel_lock;
58#endif
59
56#endif /* _IEEE1394_TRANSACTIONS_H */ 60#endif /* _IEEE1394_TRANSACTIONS_H */
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
index 16fd2d0b5ed2..a8de375e79b7 100644
--- a/drivers/ieee1394/ieee1394_types.h
+++ b/drivers/ieee1394/ieee1394_types.h
@@ -2,31 +2,9 @@
2#define _IEEE1394_TYPES_H 2#define _IEEE1394_TYPES_H
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/list.h>
6#include <linux/spinlock.h>
7#include <linux/string.h> 5#include <linux/string.h>
8#include <linux/types.h> 6#include <linux/types.h>
9
10#include <asm/byteorder.h> 7#include <asm/byteorder.h>
11#include <asm/semaphore.h>
12
13/* Transaction Label handling */
14struct hpsb_tlabel_pool {
15 DECLARE_BITMAP(pool, 64);
16 spinlock_t lock;
17 u8 next;
18 u32 allocations;
19 struct semaphore count;
20};
21
22#define HPSB_TPOOL_INIT(_tp) \
23do { \
24 bitmap_zero((_tp)->pool, 64); \
25 spin_lock_init(&(_tp)->lock); \
26 (_tp)->next = 0; \
27 (_tp)->allocations = 0; \
28 sema_init(&(_tp)->count, 63); \
29} while (0)
30 8
31typedef u32 quadlet_t; 9typedef u32 quadlet_t;
32typedef u64 octlet_t; 10typedef u64 octlet_t;
@@ -61,6 +39,7 @@ typedef u16 arm_length_t;
61 39
62#ifdef CONFIG_IEEE1394_VERBOSEDEBUG 40#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
63#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) 41#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
42#define HPSB_DEBUG_TLABELS
64#else 43#else
65#define HPSB_VERBOSE(fmt, args...) 44#define HPSB_VERBOSE(fmt, args...)
66#endif 45#endif
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index f8f6079cc48c..eabc51b23c0b 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -327,34 +327,44 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribut
327static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); 327static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
328 328
329 329
330/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically 330#ifdef HPSB_DEBUG_TLABELS
331 * here, therefore displayed values may be occasionally wrong. */ 331static ssize_t fw_show_ne_tlabels_free(struct device *dev,
332static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf) 332 struct device_attribute *attr, char *buf)
333{ 333{
334 struct node_entry *ne = container_of(dev, struct node_entry, device); 334 struct node_entry *ne = container_of(dev, struct node_entry, device);
335 return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64)); 335 unsigned long flags;
336} 336 unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
337static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); 337 int tf;
338 338
339 spin_lock_irqsave(&hpsb_tlabel_lock, flags);
340 tf = 64 - bitmap_weight(tp, 64);
341 spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
339 342
340static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf) 343 return sprintf(buf, "%d\n", tf);
341{
342 struct node_entry *ne = container_of(dev, struct node_entry, device);
343 return sprintf(buf, "%u\n", ne->tpool->allocations);
344} 344}
345static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL); 345static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
346 346
347 347
348static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf) 348static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
349 struct device_attribute *attr, char *buf)
349{ 350{
350 struct node_entry *ne = container_of(dev, struct node_entry, device); 351 struct node_entry *ne = container_of(dev, struct node_entry, device);
352 unsigned long flags;
353 unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
354 u64 tm;
355
356 spin_lock_irqsave(&hpsb_tlabel_lock, flags);
351#if (BITS_PER_LONG <= 32) 357#if (BITS_PER_LONG <= 32)
352 return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); 358 tm = ((u64)tp[0] << 32) + tp[1];
353#else 359#else
354 return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); 360 tm = tp[0];
355#endif 361#endif
362 spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
363
364 return sprintf(buf, "0x%016llx\n", tm);
356} 365}
357static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); 366static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
367#endif /* HPSB_DEBUG_TLABELS */
358 368
359 369
360static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 370static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -461,9 +471,10 @@ static struct device_attribute *const fw_ne_attrs[] = {
461 &dev_attr_ne_vendor_id, 471 &dev_attr_ne_vendor_id,
462 &dev_attr_ne_nodeid, 472 &dev_attr_ne_nodeid,
463 &dev_attr_bus_options, 473 &dev_attr_bus_options,
474#ifdef HPSB_DEBUG_TLABELS
464 &dev_attr_tlabels_free, 475 &dev_attr_tlabels_free,
465 &dev_attr_tlabels_allocations,
466 &dev_attr_tlabels_mask, 476 &dev_attr_tlabels_mask,
477#endif
467}; 478};
468 479
469 480
@@ -782,8 +793,6 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
782 if (!ne) 793 if (!ne)
783 return NULL; 794 return NULL;
784 795
785 ne->tpool = &host->tpool[nodeid & NODE_MASK];
786
787 ne->host = host; 796 ne->host = host;
788 ne->nodeid = nodeid; 797 ne->nodeid = nodeid;
789 ne->generation = generation; 798 ne->generation = generation;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index f649c9d321b8..0e1e7d930783 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -107,7 +107,6 @@ struct node_entry {
107 const char *vendor_oui; 107 const char *vendor_oui;
108 108
109 u32 capabilities; 109 u32 capabilities;
110 struct hpsb_tlabel_pool *tpool;
111 110
112 struct device device; 111 struct device device;
113 struct class_device class_dev; 112 struct class_device class_dev;