Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32 716 lines 20 kB view raw
1/* 2 * Firmware I/O code for mac80211 Prism54 drivers 3 * 4 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> 5 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de> 6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 7 * 8 * Based on: 9 * - the islsm (softmac prism54) driver, which is: 10 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. 11 * - stlc45xx driver 12 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License version 2 as 16 * published by the Free Software Foundation. 17 */ 18 19#include <linux/init.h> 20#include <linux/firmware.h> 21#include <linux/etherdevice.h> 22 23#include <net/mac80211.h> 24 25#include "p54.h" 26#include "eeprom.h" 27#include "lmac.h" 28 29int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) 30{ 31 struct p54_common *priv = dev->priv; 32 struct exp_if *exp_if; 33 struct bootrec *bootrec; 34 u32 *data = (u32 *)fw->data; 35 u32 *end_data = (u32 *)fw->data + (fw->size >> 2); 36 u8 *fw_version = NULL; 37 size_t len; 38 int i; 39 int maxlen; 40 41 if (priv->rx_start) 42 return 0; 43 44 while (data < end_data && *data) 45 data++; 46 47 while (data < end_data && !*data) 48 data++; 49 50 bootrec = (struct bootrec *) data; 51 52 while (bootrec->data <= end_data && (bootrec->data + 53 (len = le32_to_cpu(bootrec->len))) <= end_data) { 54 u32 code = le32_to_cpu(bootrec->code); 55 switch (code) { 56 case BR_CODE_COMPONENT_ID: 57 priv->fw_interface = be32_to_cpup((__be32 *) 58 bootrec->data); 59 switch (priv->fw_interface) { 60 case FW_LM86: 61 case FW_LM20: 62 case FW_LM87: { 63 char *iftype = (char *)bootrec->data; 64 printk(KERN_INFO "%s: p54 detected a LM%c%c " 65 "firmware\n", 66 wiphy_name(priv->hw->wiphy), 67 iftype[2], iftype[3]); 68 break; 69 } 70 case FW_FMAC: 71 default: 72 printk(KERN_ERR "%s: unsupported firmware\n", 73 wiphy_name(priv->hw->wiphy)); 74 return -ENODEV; 75 } 76 break; 77 case BR_CODE_COMPONENT_VERSION: 78 /* 24 bytes should be enough for all firmwares */ 79 if (strnlen((unsigned char *) bootrec->data, 24) < 24) 80 fw_version = (unsigned char *) bootrec->data; 81 break; 82 case BR_CODE_DESCR: { 83 struct bootrec_desc *desc = 84 (struct bootrec_desc *)bootrec->data; 85 priv->rx_start = le32_to_cpu(desc->rx_start); 86 /* FIXME add sanity checking */ 87 priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500; 88 priv->headroom = desc->headroom; 89 priv->tailroom = desc->tailroom; 90 priv->privacy_caps = desc->privacy_caps; 91 priv->rx_keycache_size = desc->rx_keycache_size; 92 if (le32_to_cpu(bootrec->len) == 11) 93 priv->rx_mtu = le16_to_cpu(desc->rx_mtu); 94 else 95 priv->rx_mtu = (size_t) 96 0x620 - priv->tx_hdr_len; 97 maxlen = priv->tx_hdr_len + /* USB devices */ 98 sizeof(struct p54_rx_data) + 99 4 + /* rx alignment */ 100 IEEE80211_MAX_FRAG_THRESHOLD; 101 if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) { 102 printk(KERN_INFO "p54: rx_mtu reduced from %d " 103 "to %d\n", priv->rx_mtu, maxlen); 104 priv->rx_mtu = maxlen; 105 } 106 break; 107 } 108 case BR_CODE_EXPOSED_IF: 109 exp_if = (struct exp_if *) bootrec->data; 110 for (i = 0; i < (len * sizeof(*exp_if) / 4); i++) 111 if (exp_if[i].if_id == cpu_to_le16(IF_ID_LMAC)) 112 priv->fw_var = le16_to_cpu(exp_if[i].variant); 113 break; 114 case BR_CODE_DEPENDENT_IF: 115 break; 116 case BR_CODE_END_OF_BRA: 117 case LEGACY_BR_CODE_END_OF_BRA: 118 end_data = NULL; 119 break; 120 default: 121 break; 122 } 123 bootrec = (struct bootrec *)&bootrec->data[len]; 124 } 125 126 if (fw_version) 127 printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n", 128 wiphy_name(priv->hw->wiphy), fw_version, 129 priv->fw_var >> 8, priv->fw_var & 0xff); 130 131 if (priv->fw_var < 0x500) 132 printk(KERN_INFO "%s: you are using an obsolete firmware. " 133 "visit http://wireless.kernel.org/en/users/Drivers/p54 " 134 "and grab one for \"kernel >= 2.6.28\"!\n", 135 wiphy_name(priv->hw->wiphy)); 136 137 if (priv->fw_var >= 0x300) { 138 /* Firmware supports QoS, use it! */ 139 140 if (priv->fw_var >= 0x500) { 141 priv->tx_stats[P54_QUEUE_AC_VO].limit = 16; 142 priv->tx_stats[P54_QUEUE_AC_VI].limit = 16; 143 priv->tx_stats[P54_QUEUE_AC_BE].limit = 16; 144 priv->tx_stats[P54_QUEUE_AC_BK].limit = 16; 145 } else { 146 priv->tx_stats[P54_QUEUE_AC_VO].limit = 3; 147 priv->tx_stats[P54_QUEUE_AC_VI].limit = 4; 148 priv->tx_stats[P54_QUEUE_AC_BE].limit = 3; 149 priv->tx_stats[P54_QUEUE_AC_BK].limit = 2; 150 } 151 priv->hw->queues = P54_QUEUE_AC_NUM; 152 } 153 154 printk(KERN_INFO "%s: cryptographic accelerator " 155 "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy), 156 (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : 157 "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP | 158 BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no", 159 (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ? 160 "YES" : "no"); 161 162 if (priv->rx_keycache_size) { 163 /* 164 * NOTE: 165 * 166 * The firmware provides at most 255 (0 - 254) slots 167 * for keys which are then used to offload decryption. 168 * As a result the 255 entry (aka 0xff) can be used 169 * safely by the driver to mark keys that didn't fit 170 * into the full cache. This trick saves us from 171 * keeping a extra list for uploaded keys. 172 */ 173 174 priv->used_rxkeys = kzalloc(BITS_TO_LONGS( 175 priv->rx_keycache_size), GFP_KERNEL); 176 177 if (!priv->used_rxkeys) 178 return -ENOMEM; 179 } 180 181 return 0; 182} 183EXPORT_SYMBOL_GPL(p54_parse_firmware); 184 185static struct sk_buff *p54_alloc_skb(struct p54_common *priv, u16 hdr_flags, 186 u16 payload_len, u16 type, gfp_t memflags) 187{ 188 struct p54_hdr *hdr; 189 struct sk_buff *skb; 190 size_t frame_len = sizeof(*hdr) + payload_len; 191 192 if (frame_len > P54_MAX_CTRL_FRAME_LEN) 193 return NULL; 194 195 if (unlikely(skb_queue_len(&priv->tx_pending) > 64)) 196 return NULL; 197 198 skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags); 199 if (!skb) 200 return NULL; 201 skb_reserve(skb, priv->tx_hdr_len); 202 203 hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr)); 204 hdr->flags = cpu_to_le16(hdr_flags); 205 hdr->len = cpu_to_le16(payload_len); 206 hdr->type = cpu_to_le16(type); 207 hdr->tries = hdr->rts_tries = 0; 208 return skb; 209} 210 211int p54_download_eeprom(struct p54_common *priv, void *buf, 212 u16 offset, u16 len) 213{ 214 struct p54_eeprom_lm86 *eeprom_hdr; 215 struct sk_buff *skb; 216 size_t eeprom_hdr_size; 217 int ret = 0; 218 219 if (priv->fw_var >= 0x509) 220 eeprom_hdr_size = sizeof(*eeprom_hdr); 221 else 222 eeprom_hdr_size = 0x4; 223 224 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, eeprom_hdr_size + 225 len, P54_CONTROL_TYPE_EEPROM_READBACK, 226 GFP_KERNEL); 227 if (unlikely(!skb)) 228 return -ENOMEM; 229 230 mutex_lock(&priv->eeprom_mutex); 231 priv->eeprom = buf; 232 eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb, 233 eeprom_hdr_size + len); 234 235 if (priv->fw_var < 0x509) { 236 eeprom_hdr->v1.offset = cpu_to_le16(offset); 237 eeprom_hdr->v1.len = cpu_to_le16(len); 238 } else { 239 eeprom_hdr->v2.offset = cpu_to_le32(offset); 240 eeprom_hdr->v2.len = cpu_to_le16(len); 241 eeprom_hdr->v2.magic2 = 0xf; 242 memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4); 243 } 244 245 p54_tx(priv, skb); 246 247 if (!wait_for_completion_interruptible_timeout( 248 &priv->eeprom_comp, HZ)) { 249 printk(KERN_ERR "%s: device does not respond!\n", 250 wiphy_name(priv->hw->wiphy)); 251 ret = -EBUSY; 252 } 253 priv->eeprom = NULL; 254 mutex_unlock(&priv->eeprom_mutex); 255 return ret; 256} 257 258int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set) 259{ 260 struct sk_buff *skb; 261 struct p54_tim *tim; 262 263 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim), 264 P54_CONTROL_TYPE_TIM, GFP_ATOMIC); 265 if (unlikely(!skb)) 266 return -ENOMEM; 267 268 tim = (struct p54_tim *) skb_put(skb, sizeof(*tim)); 269 tim->count = 1; 270 tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid); 271 p54_tx(priv, skb); 272 return 0; 273} 274 275int p54_sta_unlock(struct p54_common *priv, u8 *addr) 276{ 277 struct sk_buff *skb; 278 struct p54_sta_unlock *sta; 279 280 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta), 281 P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); 282 if (unlikely(!skb)) 283 return -ENOMEM; 284 285 sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta)); 286 memcpy(sta->addr, addr, ETH_ALEN); 287 p54_tx(priv, skb); 288 return 0; 289} 290 291int p54_tx_cancel(struct p54_common *priv, __le32 req_id) 292{ 293 struct sk_buff *skb; 294 struct p54_txcancel *cancel; 295 u32 _req_id = le32_to_cpu(req_id); 296 297 if (unlikely(_req_id < priv->rx_start || _req_id > priv->rx_end)) 298 return -EINVAL; 299 300 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel), 301 P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); 302 if (unlikely(!skb)) 303 return -ENOMEM; 304 305 cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel)); 306 cancel->req_id = req_id; 307 p54_tx(priv, skb); 308 return 0; 309} 310 311int p54_setup_mac(struct p54_common *priv) 312{ 313 struct sk_buff *skb; 314 struct p54_setup_mac *setup; 315 u16 mode; 316 317 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup), 318 P54_CONTROL_TYPE_SETUP, GFP_ATOMIC); 319 if (!skb) 320 return -ENOMEM; 321 322 setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup)); 323 if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) { 324 switch (priv->mode) { 325 case NL80211_IFTYPE_STATION: 326 mode = P54_FILTER_TYPE_STATION; 327 break; 328 case NL80211_IFTYPE_AP: 329 mode = P54_FILTER_TYPE_AP; 330 break; 331 case NL80211_IFTYPE_ADHOC: 332 case NL80211_IFTYPE_MESH_POINT: 333 mode = P54_FILTER_TYPE_IBSS; 334 break; 335 case NL80211_IFTYPE_MONITOR: 336 mode = P54_FILTER_TYPE_PROMISCUOUS; 337 break; 338 default: 339 mode = P54_FILTER_TYPE_HIBERNATE; 340 break; 341 } 342 343 /* 344 * "TRANSPARENT and PROMISCUOUS are mutually exclusive" 345 * STSW45X0C LMAC API - page 12 346 */ 347 if (((priv->filter_flags & FIF_PROMISC_IN_BSS) || 348 (priv->filter_flags & FIF_OTHER_BSS)) && 349 (mode != P54_FILTER_TYPE_PROMISCUOUS)) 350 mode |= P54_FILTER_TYPE_TRANSPARENT; 351 } else { 352 mode = P54_FILTER_TYPE_HIBERNATE; 353 } 354 355 setup->mac_mode = cpu_to_le16(mode); 356 memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); 357 memcpy(setup->bssid, priv->bssid, ETH_ALEN); 358 setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */ 359 setup->rx_align = 0; 360 if (priv->fw_var < 0x500) { 361 setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 362 memset(setup->v1.rts_rates, 0, 8); 363 setup->v1.rx_addr = cpu_to_le32(priv->rx_end); 364 setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); 365 setup->v1.rxhw = cpu_to_le16(priv->rxhw); 366 setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer); 367 setup->v1.unalloc0 = cpu_to_le16(0); 368 } else { 369 setup->v2.rx_addr = cpu_to_le32(priv->rx_end); 370 setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); 371 setup->v2.rxhw = cpu_to_le16(priv->rxhw); 372 setup->v2.timer = cpu_to_le16(priv->wakeup_timer); 373 setup->v2.truncate = cpu_to_le16(48896); 374 setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 375 setup->v2.sbss_offset = 0; 376 setup->v2.mcast_window = 0; 377 setup->v2.rx_rssi_threshold = 0; 378 setup->v2.rx_ed_threshold = 0; 379 setup->v2.ref_clock = cpu_to_le32(644245094); 380 setup->v2.lpf_bandwidth = cpu_to_le16(65535); 381 setup->v2.osc_start_delay = cpu_to_le16(65535); 382 } 383 p54_tx(priv, skb); 384 return 0; 385} 386 387int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) 388{ 389 struct sk_buff *skb; 390 struct p54_hdr *hdr; 391 struct p54_scan_head *head; 392 struct p54_iq_autocal_entry *iq_autocal; 393 union p54_scan_body_union *body; 394 struct p54_scan_tail_rate *rate; 395 struct pda_rssi_cal_entry *rssi; 396 unsigned int i; 397 void *entry; 398 int band = priv->hw->conf.channel->band; 399 __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq); 400 401 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + 402 2 + sizeof(*iq_autocal) + sizeof(*body) + 403 sizeof(*rate) + 2 * sizeof(*rssi), 404 P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); 405 if (!skb) 406 return -ENOMEM; 407 408 head = (struct p54_scan_head *) skb_put(skb, sizeof(*head)); 409 memset(head->scan_params, 0, sizeof(head->scan_params)); 410 head->mode = cpu_to_le16(mode); 411 head->dwell = cpu_to_le16(dwell); 412 head->freq = freq; 413 414 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 415 __le16 *pa_power_points = (__le16 *) skb_put(skb, 2); 416 *pa_power_points = cpu_to_le16(0x0c); 417 } 418 419 iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal)); 420 for (i = 0; i < priv->iq_autocal_len; i++) { 421 if (priv->iq_autocal[i].freq != freq) 422 continue; 423 424 memcpy(iq_autocal, &priv->iq_autocal[i].params, 425 sizeof(struct p54_iq_autocal_entry)); 426 break; 427 } 428 if (i == priv->iq_autocal_len) 429 goto err; 430 431 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) 432 body = (void *) skb_put(skb, sizeof(body->longbow)); 433 else 434 body = (void *) skb_put(skb, sizeof(body->normal)); 435 436 for (i = 0; i < priv->output_limit->entries; i++) { 437 __le16 *entry_freq = (void *) (priv->output_limit->data + 438 priv->output_limit->entry_size * i); 439 440 if (*entry_freq != freq) 441 continue; 442 443 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 444 memcpy(&body->longbow.power_limits, 445 (void *) entry_freq + sizeof(__le16), 446 priv->output_limit->entry_size); 447 } else { 448 struct pda_channel_output_limit *limits = 449 (void *) entry_freq; 450 451 body->normal.val_barker = 0x38; 452 body->normal.val_bpsk = body->normal.dup_bpsk = 453 limits->val_bpsk; 454 body->normal.val_qpsk = body->normal.dup_qpsk = 455 limits->val_qpsk; 456 body->normal.val_16qam = body->normal.dup_16qam = 457 limits->val_16qam; 458 body->normal.val_64qam = body->normal.dup_64qam = 459 limits->val_64qam; 460 } 461 break; 462 } 463 if (i == priv->output_limit->entries) 464 goto err; 465 466 entry = (void *)(priv->curve_data->data + priv->curve_data->offset); 467 for (i = 0; i < priv->curve_data->entries; i++) { 468 if (*((__le16 *)entry) != freq) { 469 entry += priv->curve_data->entry_size; 470 continue; 471 } 472 473 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 474 memcpy(&body->longbow.curve_data, 475 (void *) entry + sizeof(__le16), 476 priv->curve_data->entry_size); 477 } else { 478 struct p54_scan_body *chan = &body->normal; 479 struct pda_pa_curve_data *curve_data = 480 (void *) priv->curve_data->data; 481 482 entry += sizeof(__le16); 483 chan->pa_points_per_curve = 8; 484 memset(chan->curve_data, 0, sizeof(*chan->curve_data)); 485 memcpy(chan->curve_data, entry, 486 sizeof(struct p54_pa_curve_data_sample) * 487 min((u8)8, curve_data->points_per_channel)); 488 } 489 break; 490 } 491 if (i == priv->curve_data->entries) 492 goto err; 493 494 if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) { 495 rate = (void *) skb_put(skb, sizeof(*rate)); 496 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 497 for (i = 0; i < sizeof(rate->rts_rates); i++) 498 rate->rts_rates[i] = i; 499 } 500 501 rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); 502 rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); 503 rssi->add = cpu_to_le16(priv->rssical_db[band].add); 504 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 505 /* Longbow frontend needs ever more */ 506 rssi = (void *) skb_put(skb, sizeof(*rssi)); 507 rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); 508 rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); 509 } 510 511 if (priv->fw_var >= 0x509) { 512 rate = (void *) skb_put(skb, sizeof(*rate)); 513 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 514 for (i = 0; i < sizeof(rate->rts_rates); i++) 515 rate->rts_rates[i] = i; 516 } 517 518 hdr = (struct p54_hdr *) skb->data; 519 hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); 520 521 p54_tx(priv, skb); 522 return 0; 523 524err: 525 printk(KERN_ERR "%s: frequency change to channel %d failed.\n", 526 wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel( 527 priv->hw->conf.channel->center_freq)); 528 529 dev_kfree_skb_any(skb); 530 return -EINVAL; 531} 532 533int p54_set_leds(struct p54_common *priv) 534{ 535 struct sk_buff *skb; 536 struct p54_led *led; 537 538 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led), 539 P54_CONTROL_TYPE_LED, GFP_ATOMIC); 540 if (unlikely(!skb)) 541 return -ENOMEM; 542 543 led = (struct p54_led *) skb_put(skb, sizeof(*led)); 544 led->flags = cpu_to_le16(0x0003); 545 led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state); 546 led->delay[0] = cpu_to_le16(1); 547 led->delay[1] = cpu_to_le16(0); 548 p54_tx(priv, skb); 549 return 0; 550} 551 552int p54_set_edcf(struct p54_common *priv) 553{ 554 struct sk_buff *skb; 555 struct p54_edcf *edcf; 556 557 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf), 558 P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC); 559 if (unlikely(!skb)) 560 return -ENOMEM; 561 562 edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf)); 563 if (priv->use_short_slot) { 564 edcf->slottime = 9; 565 edcf->sifs = 0x10; 566 edcf->eofpad = 0x00; 567 } else { 568 edcf->slottime = 20; 569 edcf->sifs = 0x0a; 570 edcf->eofpad = 0x06; 571 } 572 /* (see prism54/isl_oid.h for further details) */ 573 edcf->frameburst = cpu_to_le16(0); 574 edcf->round_trip_delay = cpu_to_le16(0); 575 edcf->flags = 0; 576 memset(edcf->mapping, 0, sizeof(edcf->mapping)); 577 memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); 578 p54_tx(priv, skb); 579 return 0; 580} 581 582int p54_set_ps(struct p54_common *priv) 583{ 584 struct sk_buff *skb; 585 struct p54_psm *psm; 586 unsigned int i; 587 u16 mode; 588 589 if (priv->hw->conf.flags & IEEE80211_CONF_PS && 590 !priv->powersave_override) 591 mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | 592 P54_PSM_CHECKSUM | P54_PSM_MCBC; 593 else 594 mode = P54_PSM_CAM; 595 596 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm), 597 P54_CONTROL_TYPE_PSM, GFP_ATOMIC); 598 if (!skb) 599 return -ENOMEM; 600 601 psm = (struct p54_psm *)skb_put(skb, sizeof(*psm)); 602 psm->mode = cpu_to_le16(mode); 603 psm->aid = cpu_to_le16(priv->aid); 604 for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) { 605 psm->intervals[i].interval = 606 cpu_to_le16(priv->hw->conf.listen_interval); 607 psm->intervals[i].periods = cpu_to_le16(1); 608 } 609 610 psm->beacon_rssi_skip_max = 200; 611 psm->rssi_delta_threshold = 0; 612 psm->nr = 1; 613 psm->exclude[0] = WLAN_EID_TIM; 614 615 p54_tx(priv, skb); 616 return 0; 617} 618 619int p54_init_xbow_synth(struct p54_common *priv) 620{ 621 struct sk_buff *skb; 622 struct p54_xbow_synth *xbow; 623 624 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow), 625 P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL); 626 if (unlikely(!skb)) 627 return -ENOMEM; 628 629 xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow)); 630 xbow->magic1 = cpu_to_le16(0x1); 631 xbow->magic2 = cpu_to_le16(0x2); 632 xbow->freq = cpu_to_le16(5390); 633 memset(xbow->padding, 0, sizeof(xbow->padding)); 634 p54_tx(priv, skb); 635 return 0; 636} 637 638int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, 639 u8 *addr, u8* key) 640{ 641 struct sk_buff *skb; 642 struct p54_keycache *rxkey; 643 644 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), 645 P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL); 646 if (unlikely(!skb)) 647 return -ENOMEM; 648 649 rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey)); 650 rxkey->entry = slot; 651 rxkey->key_id = idx; 652 rxkey->key_type = algo; 653 if (addr) 654 memcpy(rxkey->mac, addr, ETH_ALEN); 655 else 656 memset(rxkey->mac, ~0, ETH_ALEN); 657 658 switch (algo) { 659 case P54_CRYPTO_WEP: 660 case P54_CRYPTO_AESCCMP: 661 rxkey->key_len = min_t(u8, 16, len); 662 memcpy(rxkey->key, key, rxkey->key_len); 663 break; 664 665 case P54_CRYPTO_TKIPMICHAEL: 666 rxkey->key_len = 24; 667 memcpy(rxkey->key, key, 16); 668 memcpy(&(rxkey->key[16]), &(key 669 [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8); 670 break; 671 672 case P54_CRYPTO_NONE: 673 rxkey->key_len = 0; 674 memset(rxkey->key, 0, sizeof(rxkey->key)); 675 break; 676 677 default: 678 printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n", 679 wiphy_name(priv->hw->wiphy), algo); 680 dev_kfree_skb(skb); 681 return -EINVAL; 682 } 683 684 p54_tx(priv, skb); 685 return 0; 686} 687 688int p54_fetch_statistics(struct p54_common *priv) 689{ 690 struct ieee80211_tx_info *txinfo; 691 struct p54_tx_info *p54info; 692 struct sk_buff *skb; 693 694 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, 695 sizeof(struct p54_statistics), 696 P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); 697 if (!skb) 698 return -ENOMEM; 699 700 /* 701 * The statistic feedback causes some extra headaches here, if it 702 * is not to crash/corrupt the firmware data structures. 703 * 704 * Unlike all other Control Get OIDs we can not use helpers like 705 * skb_put to reserve the space for the data we're requesting. 706 * Instead the extra frame length -which will hold the results later- 707 * will only be told to the p54_assign_address, so that following 708 * frames won't be placed into the allegedly empty area. 709 */ 710 txinfo = IEEE80211_SKB_CB(skb); 711 p54info = (void *) txinfo->rate_driver_data; 712 p54info->extra_len = sizeof(struct p54_statistics); 713 714 p54_tx(priv, skb); 715 return 0; 716}