Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ip27-hubio.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.
3  * Copyright (C) 2004 Christoph Hellwig.
4  * Released under GPL v2.
5  *
6  * Support functions for the HUB ASIC - mostly PIO mapping related.
7  */
8 
9 #include <linux/bitops.h>
10 #include <linux/string.h>
11 #include <linux/mmzone.h>
12 #include <asm/sn/addrs.h>
13 #include <asm/sn/arch.h>
14 #include <asm/sn/hub.h>
15 
16 
17 static int force_fire_and_forget = 1;
18 
28 unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
29  unsigned long xtalk_addr, size_t size)
30 {
31  nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
32  unsigned i;
33 
34  /* use small-window mapping if possible */
35  if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE)
36  return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE);
37 
38  if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) {
39  printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx"
40  " too big (%ld)\n",
41  nasid, widget, xtalk_addr, size);
42  return 0;
43  }
44 
45  xtalk_addr &= ~(BWIN_SIZE-1);
46  for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) {
47  if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used))
48  continue;
49 
50  /*
51  * The code below does a PIO write to setup an ITTE entry.
52  *
53  * We need to prevent other CPUs from seeing our updated
54  * memory shadow of the ITTE (in the piomap) until the ITTE
55  * entry is actually set up; otherwise, another CPU might
56  * attempt a PIO prematurely.
57  *
58  * Also, the only way we can know that an entry has been
59  * received by the hub and can be used by future PIO reads/
60  * writes is by reading back the ITTE entry after writing it.
61  *
62  * For these two reasons, we PIO read back the ITTE entry
63  * after we write it.
64  */
65  IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
66  (void) HUB_L(IIO_ITTE_GET(nasid, i));
67 
68  return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
69  }
70 
71  printk(KERN_WARNING "unable to establish PIO mapping for at"
72  " hub %d widget %d addr 0x%lx\n",
73  nasid, widget, xtalk_addr);
74  return 0;
75 }
76 
77 
78 /*
79  * hub_setup_prb(nasid, prbnum, credits, conveyor)
80  *
81  * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise,
82  * put it into conveyor belt mode with the specified number of credits.
83  */
84 static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
85 {
86  iprb_t prb;
87  int prb_offset;
88 
89  /*
90  * Get the current register value.
91  */
92  prb_offset = IIO_IOPRB(prbnum);
93  prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
94 
95  /*
96  * Clear out some fields.
97  */
98  prb.iprb_ovflow = 1;
99  prb.iprb_bnakctr = 0;
100  prb.iprb_anakctr = 0;
101 
102  /*
103  * Enable or disable fire-and-forget mode.
104  */
105  prb.iprb_ff = force_fire_and_forget ? 1 : 0;
106 
107  /*
108  * Set the appropriate number of PIO cresits for the widget.
109  */
110  prb.iprb_xtalkctr = credits;
111 
112  /*
113  * Store the new value to the register.
114  */
115  REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
116 }
117 
136 static void hub_set_piomode(nasid_t nasid)
137 {
138  hubreg_t ii_iowa;
139  hubii_wcr_t ii_wcr;
140  unsigned i;
141 
142  ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
144 
145  ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
146 
147  if (ii_wcr.iwcr_dir_con) {
148  /*
149  * Assume a bridge here.
150  */
151  hub_setup_prb(nasid, 0, 3);
152  } else {
153  /*
154  * Assume a crossbow here.
155  */
156  hub_setup_prb(nasid, 0, 1);
157  }
158 
159  /*
160  * XXX - Here's where we should take the widget type into
161  * when account assigning credits.
162  */
163  for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
164  hub_setup_prb(nasid, i, 3);
165 
166  REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
167 }
168 
169 /*
170  * hub_pio_init - PIO-related hub initialization
171  *
172  * @hub: hubinfo structure for our hub
173  */
175 {
176  nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
177  unsigned i;
178 
179  /* initialize big window piomaps for this hub */
180  bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW);
181  for (i = 0; i < HUB_NUM_BIG_WINDOW; i++)
182  IIO_ITTE_DISABLE(nasid, i);
183 
184  hub_set_piomode(nasid);
185 }