GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / usb / wusbcore / mmc.c
blob3e3ff3577576f7ab1a59c218ea41f4113f3e09df
2 #include <linux/usb/wusb.h>
3 #include <linux/slab.h>
4 #include "wusbhc.h"
6 /* Initialize the MMCIEs handling mechanism */
7 int wusbhc_mmcie_create(struct wusbhc *wusbhc)
9 u8 mmcies = wusbhc->mmcies_max;
10 wusbhc->mmcie = kcalloc(mmcies, sizeof(wusbhc->mmcie[0]), GFP_KERNEL);
11 if (wusbhc->mmcie == NULL)
12 return -ENOMEM;
13 mutex_init(&wusbhc->mmcie_mutex);
14 return 0;
17 /* Release resources used by the MMCIEs handling mechanism */
18 void wusbhc_mmcie_destroy(struct wusbhc *wusbhc)
20 kfree(wusbhc->mmcie);
24 * Add or replace an MMC Wireless USB IE.
26 * @interval: See WUSB1.0[8.5.3.1]
27 * @repeat_cnt: See WUSB1.0[8.5.3.1]
28 * @handle: See WUSB1.0[8.5.3.1]
29 * @wuie: Pointer to the header of the WUSB IE data to add.
30 * MUST BE allocated in a kmalloc buffer (no stack or
31 * vmalloc).
32 * THE CALLER ALWAYS OWNS THE POINTER (we don't free it
33 * on remove, we just forget about it).
34 * @returns: 0 if ok, < 0 errno code on error.
36 * Goes over the *whole* @wusbhc->mmcie array looking for (a) the
37 * first free spot and (b) if @wuie is already in the array (aka:
38 * transmitted in the MMCs) the spot were it is.
40 * If present, we "overwrite it" (update).
43 * NOTE: Need special ordering rules -- see below WUSB1.0 Table 7-38.
44 * The host uses the handle as the 'sort' index. We
45 * allocate the last one always for the WUIE_ID_HOST_INFO, and
46 * the rest, first come first serve in inverse order.
48 * Host software must make sure that it adds the other IEs in
49 * the right order... the host hardware is responsible for
50 * placing the WCTA IEs in the right place with the other IEs
51 * set by host software.
53 * NOTE: we can access wusbhc->wa_descr without locking because it is
54 * read only.
56 int wusbhc_mmcie_set(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
57 struct wuie_hdr *wuie)
59 int result = -ENOBUFS;
60 unsigned handle, itr;
62 /* Search a handle, taking into account the ordering */
63 mutex_lock(&wusbhc->mmcie_mutex);
64 switch (wuie->bIEIdentifier) {
65 case WUIE_ID_HOST_INFO:
66 /* Always last */
67 handle = wusbhc->mmcies_max - 1;
68 break;
69 case WUIE_ID_ISOCH_DISCARD:
70 dev_err(wusbhc->dev, "Special ordering case for WUIE ID 0x%x "
71 "unimplemented\n", wuie->bIEIdentifier);
72 result = -ENOSYS;
73 goto error_unlock;
74 default:
75 /* search for it or find the last empty slot */
76 handle = ~0;
77 for (itr = 0; itr < wusbhc->mmcies_max - 1; itr++) {
78 if (wusbhc->mmcie[itr] == wuie) {
79 handle = itr;
80 break;
82 if (wusbhc->mmcie[itr] == NULL)
83 handle = itr;
85 if (handle == ~0)
86 goto error_unlock;
88 result = (wusbhc->mmcie_add)(wusbhc, interval, repeat_cnt, handle,
89 wuie);
90 if (result >= 0)
91 wusbhc->mmcie[handle] = wuie;
92 error_unlock:
93 mutex_unlock(&wusbhc->mmcie_mutex);
94 return result;
96 EXPORT_SYMBOL_GPL(wusbhc_mmcie_set);
99 * Remove an MMC IE previously added with wusbhc_mmcie_set()
101 * @wuie Pointer used to add the WUIE
103 void wusbhc_mmcie_rm(struct wusbhc *wusbhc, struct wuie_hdr *wuie)
105 int result;
106 unsigned handle, itr;
108 mutex_lock(&wusbhc->mmcie_mutex);
109 for (itr = 0; itr < wusbhc->mmcies_max; itr++) {
110 if (wusbhc->mmcie[itr] == wuie) {
111 handle = itr;
112 goto found;
115 mutex_unlock(&wusbhc->mmcie_mutex);
116 return;
118 found:
119 result = (wusbhc->mmcie_rm)(wusbhc, handle);
120 if (result == 0)
121 wusbhc->mmcie[itr] = NULL;
122 mutex_unlock(&wusbhc->mmcie_mutex);
124 EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm);
126 static int wusbhc_mmc_start(struct wusbhc *wusbhc)
128 int ret;
130 mutex_lock(&wusbhc->mutex);
131 ret = wusbhc->start(wusbhc);
132 if (ret >= 0)
133 wusbhc->active = 1;
134 mutex_unlock(&wusbhc->mutex);
136 return ret;
139 static void wusbhc_mmc_stop(struct wusbhc *wusbhc)
141 mutex_lock(&wusbhc->mutex);
142 wusbhc->active = 0;
143 wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS);
144 mutex_unlock(&wusbhc->mutex);
148 * wusbhc_start - start transmitting MMCs and accepting connections
149 * @wusbhc: the HC to start
151 * Establishes a cluster reservation, enables device connections, and
152 * starts MMCs with appropriate DNTS parameters.
154 int wusbhc_start(struct wusbhc *wusbhc)
156 int result;
157 struct device *dev = wusbhc->dev;
159 WARN_ON(wusbhc->wuie_host_info != NULL);
161 result = wusbhc_rsv_establish(wusbhc);
162 if (result < 0) {
163 dev_err(dev, "cannot establish cluster reservation: %d\n",
164 result);
165 goto error_rsv_establish;
168 result = wusbhc_devconnect_start(wusbhc);
169 if (result < 0) {
170 dev_err(dev, "error enabling device connections: %d\n", result);
171 goto error_devconnect_start;
174 result = wusbhc_sec_start(wusbhc);
175 if (result < 0) {
176 dev_err(dev, "error starting security in the HC: %d\n", result);
177 goto error_sec_start;
179 result = wusbhc->set_num_dnts(wusbhc, 0, 15);
180 if (result < 0) {
181 dev_err(dev, "Cannot set DNTS parameters: %d\n", result);
182 goto error_set_num_dnts;
184 result = wusbhc_mmc_start(wusbhc);
185 if (result < 0) {
186 dev_err(dev, "error starting wusbch: %d\n", result);
187 goto error_wusbhc_start;
190 return 0;
192 error_wusbhc_start:
193 wusbhc_sec_stop(wusbhc);
194 error_set_num_dnts:
195 error_sec_start:
196 wusbhc_devconnect_stop(wusbhc);
197 error_devconnect_start:
198 wusbhc_rsv_terminate(wusbhc);
199 error_rsv_establish:
200 return result;
204 * wusbhc_stop - stop transmitting MMCs
205 * @wusbhc: the HC to stop
207 * Stops the WUSB channel and removes the cluster reservation.
209 void wusbhc_stop(struct wusbhc *wusbhc)
211 wusbhc_mmc_stop(wusbhc);
212 wusbhc_sec_stop(wusbhc);
213 wusbhc_devconnect_stop(wusbhc);
214 wusbhc_rsv_terminate(wusbhc);
218 * Set/reset/update a new CHID
220 * Depending on the previous state of the MMCs, start, stop or change
221 * the sent MMC. This effectively switches the host controller on and
222 * off (radio wise).
224 int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
226 int result = 0;
228 if (memcmp(chid, &wusb_ckhdid_zero, sizeof(*chid)) == 0)
229 chid = NULL;
231 mutex_lock(&wusbhc->mutex);
232 if (chid) {
233 if (wusbhc->active) {
234 mutex_unlock(&wusbhc->mutex);
235 return -EBUSY;
237 wusbhc->chid = *chid;
239 mutex_unlock(&wusbhc->mutex);
241 if (chid)
242 result = uwb_radio_start(&wusbhc->pal);
243 else
244 uwb_radio_stop(&wusbhc->pal);
245 return result;
247 EXPORT_SYMBOL_GPL(wusbhc_chid_set);