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