diff options
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 90 |
1 files changed, 38 insertions, 52 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 3ca9386561ff..850857932e29 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -394,7 +394,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
394 | while (entry != (struct sk_buff *)&priv->tx_queue) { | 394 | while (entry != (struct sk_buff *)&priv->tx_queue) { |
395 | range = (struct memrecord *)&entry->cb; | 395 | range = (struct memrecord *)&entry->cb; |
396 | if (range->start_addr == addr) { | 396 | if (range->start_addr == addr) { |
397 | struct ieee80211_tx_status status; | 397 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); |
398 | struct p54_control_hdr *entry_hdr; | 398 | struct p54_control_hdr *entry_hdr; |
399 | struct p54_tx_control_allocdata *entry_data; | 399 | struct p54_tx_control_allocdata *entry_data; |
400 | int pad = 0; | 400 | int pad = 0; |
@@ -406,30 +406,23 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
406 | 406 | ||
407 | last_addr = range->end_addr; | 407 | last_addr = range->end_addr; |
408 | __skb_unlink(entry, &priv->tx_queue); | 408 | __skb_unlink(entry, &priv->tx_queue); |
409 | if (!range->control) { | 409 | memset(&info->status, 0, sizeof(info->status)); |
410 | kfree_skb(entry); | 410 | priv->tx_stats[info->queue].len--; |
411 | break; | ||
412 | } | ||
413 | memset(&status, 0, sizeof(status)); | ||
414 | memcpy(&status.control, range->control, | ||
415 | sizeof(status.control)); | ||
416 | kfree(range->control); | ||
417 | priv->tx_stats[status.control.queue].len--; | ||
418 | entry_hdr = (struct p54_control_hdr *) entry->data; | 411 | entry_hdr = (struct p54_control_hdr *) entry->data; |
419 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; | 412 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; |
420 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) | 413 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) |
421 | pad = entry_data->align[0]; | 414 | pad = entry_data->align[0]; |
422 | 415 | ||
423 | if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) { | 416 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
424 | if (!(payload->status & 0x01)) | 417 | if (!(payload->status & 0x01)) |
425 | status.flags |= IEEE80211_TX_STATUS_ACK; | 418 | info->flags |= IEEE80211_TX_STAT_ACK; |
426 | else | 419 | else |
427 | status.excessive_retries = 1; | 420 | info->status.excessive_retries = 1; |
428 | } | 421 | } |
429 | status.retry_count = payload->retries - 1; | 422 | info->status.retry_count = payload->retries - 1; |
430 | status.ack_signal = le16_to_cpu(payload->ack_rssi); | 423 | info->status.ack_signal = le16_to_cpu(payload->ack_rssi); |
431 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); | 424 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); |
432 | ieee80211_tx_status_irqsafe(dev, entry, &status); | 425 | ieee80211_tx_status_irqsafe(dev, entry); |
433 | break; | 426 | break; |
434 | } else | 427 | } else |
435 | last_addr = range->end_addr; | 428 | last_addr = range->end_addr; |
@@ -494,13 +487,11 @@ EXPORT_SYMBOL_GPL(p54_rx); | |||
494 | * allocated areas. | 487 | * allocated areas. |
495 | */ | 488 | */ |
496 | static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | 489 | static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, |
497 | struct p54_control_hdr *data, u32 len, | 490 | struct p54_control_hdr *data, u32 len) |
498 | struct ieee80211_tx_control *control) | ||
499 | { | 491 | { |
500 | struct p54_common *priv = dev->priv; | 492 | struct p54_common *priv = dev->priv; |
501 | struct sk_buff *entry = priv->tx_queue.next; | 493 | struct sk_buff *entry = priv->tx_queue.next; |
502 | struct sk_buff *target_skb = NULL; | 494 | struct sk_buff *target_skb = NULL; |
503 | struct memrecord *range; | ||
504 | u32 last_addr = priv->rx_start; | 495 | u32 last_addr = priv->rx_start; |
505 | u32 largest_hole = 0; | 496 | u32 largest_hole = 0; |
506 | u32 target_addr = priv->rx_start; | 497 | u32 target_addr = priv->rx_start; |
@@ -512,7 +503,8 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
512 | left = skb_queue_len(&priv->tx_queue); | 503 | left = skb_queue_len(&priv->tx_queue); |
513 | while (left--) { | 504 | while (left--) { |
514 | u32 hole_size; | 505 | u32 hole_size; |
515 | range = (struct memrecord *)&entry->cb; | 506 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); |
507 | struct memrecord *range = (void *)info->driver_data; | ||
516 | hole_size = range->start_addr - last_addr; | 508 | hole_size = range->start_addr - last_addr; |
517 | if (!target_skb && hole_size >= len) { | 509 | if (!target_skb && hole_size >= len) { |
518 | target_skb = entry->prev; | 510 | target_skb = entry->prev; |
@@ -527,17 +519,18 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
527 | target_skb = priv->tx_queue.prev; | 519 | target_skb = priv->tx_queue.prev; |
528 | largest_hole = max(largest_hole, priv->rx_end - last_addr - len); | 520 | largest_hole = max(largest_hole, priv->rx_end - last_addr - len); |
529 | if (!skb_queue_empty(&priv->tx_queue)) { | 521 | if (!skb_queue_empty(&priv->tx_queue)) { |
530 | range = (struct memrecord *)&target_skb->cb; | 522 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb); |
523 | struct memrecord *range = (void *)info->driver_data; | ||
531 | target_addr = range->end_addr; | 524 | target_addr = range->end_addr; |
532 | } | 525 | } |
533 | } else | 526 | } else |
534 | largest_hole = max(largest_hole, priv->rx_end - last_addr); | 527 | largest_hole = max(largest_hole, priv->rx_end - last_addr); |
535 | 528 | ||
536 | if (skb) { | 529 | if (skb) { |
537 | range = (struct memrecord *)&skb->cb; | 530 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
531 | struct memrecord *range = (void *)info->driver_data; | ||
538 | range->start_addr = target_addr; | 532 | range->start_addr = target_addr; |
539 | range->end_addr = target_addr + len; | 533 | range->end_addr = target_addr + len; |
540 | range->control = control; | ||
541 | __skb_queue_after(&priv->tx_queue, target_skb, skb); | 534 | __skb_queue_after(&priv->tx_queue, target_skb, skb); |
542 | if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 + | 535 | if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 + |
543 | sizeof(struct p54_control_hdr)) | 536 | sizeof(struct p54_control_hdr)) |
@@ -548,32 +541,27 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
548 | data->req_id = cpu_to_le32(target_addr + 0x70); | 541 | data->req_id = cpu_to_le32(target_addr + 0x70); |
549 | } | 542 | } |
550 | 543 | ||
551 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, | 544 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
552 | struct ieee80211_tx_control *control) | ||
553 | { | 545 | { |
546 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
554 | struct ieee80211_tx_queue_stats *current_queue; | 547 | struct ieee80211_tx_queue_stats *current_queue; |
555 | struct p54_common *priv = dev->priv; | 548 | struct p54_common *priv = dev->priv; |
556 | struct p54_control_hdr *hdr; | 549 | struct p54_control_hdr *hdr; |
557 | struct p54_tx_control_allocdata *txhdr; | 550 | struct p54_tx_control_allocdata *txhdr; |
558 | struct ieee80211_tx_control *control_copy; | ||
559 | size_t padding, len; | 551 | size_t padding, len; |
560 | u8 rate; | 552 | u8 rate; |
561 | 553 | ||
562 | current_queue = &priv->tx_stats[control->queue]; | 554 | current_queue = &priv->tx_stats[info->queue]; |
563 | if (unlikely(current_queue->len > current_queue->limit)) | 555 | if (unlikely(current_queue->len > current_queue->limit)) |
564 | return NETDEV_TX_BUSY; | 556 | return NETDEV_TX_BUSY; |
565 | current_queue->len++; | 557 | current_queue->len++; |
566 | current_queue->count++; | 558 | current_queue->count++; |
567 | if (current_queue->len == current_queue->limit) | 559 | if (current_queue->len == current_queue->limit) |
568 | ieee80211_stop_queue(dev, control->queue); | 560 | ieee80211_stop_queue(dev, info->queue); |
569 | 561 | ||
570 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; | 562 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; |
571 | len = skb->len; | 563 | len = skb->len; |
572 | 564 | ||
573 | control_copy = kmalloc(sizeof(*control), GFP_ATOMIC); | ||
574 | if (control_copy) | ||
575 | memcpy(control_copy, control, sizeof(*control)); | ||
576 | |||
577 | txhdr = (struct p54_tx_control_allocdata *) | 565 | txhdr = (struct p54_tx_control_allocdata *) |
578 | skb_push(skb, sizeof(*txhdr) + padding); | 566 | skb_push(skb, sizeof(*txhdr) + padding); |
579 | hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr)); | 567 | hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr)); |
@@ -583,35 +571,37 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
583 | else | 571 | else |
584 | hdr->magic1 = cpu_to_le16(0x0010); | 572 | hdr->magic1 = cpu_to_le16(0x0010); |
585 | hdr->len = cpu_to_le16(len); | 573 | hdr->len = cpu_to_le16(len); |
586 | hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1); | 574 | hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); |
587 | hdr->retry1 = hdr->retry2 = control->retry_limit; | 575 | hdr->retry1 = hdr->retry2 = info->control.retry_limit; |
588 | p54_assign_address(dev, skb, hdr, skb->len, control_copy); | ||
589 | 576 | ||
590 | memset(txhdr->wep_key, 0x0, 16); | 577 | memset(txhdr->wep_key, 0x0, 16); |
591 | txhdr->padding = 0; | 578 | txhdr->padding = 0; |
592 | txhdr->padding2 = 0; | 579 | txhdr->padding2 = 0; |
593 | 580 | ||
594 | /* TODO: add support for alternate retry TX rates */ | 581 | /* TODO: add support for alternate retry TX rates */ |
595 | rate = ieee80211_get_tx_rate(dev, control)->hw_value; | 582 | rate = ieee80211_get_tx_rate(dev, info)->hw_value; |
596 | if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) | 583 | if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) |
597 | rate |= 0x10; | 584 | rate |= 0x10; |
598 | if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) | 585 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
599 | rate |= 0x40; | 586 | rate |= 0x40; |
600 | else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) | 587 | else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) |
601 | rate |= 0x20; | 588 | rate |= 0x20; |
602 | memset(txhdr->rateset, rate, 8); | 589 | memset(txhdr->rateset, rate, 8); |
603 | txhdr->wep_key_present = 0; | 590 | txhdr->wep_key_present = 0; |
604 | txhdr->wep_key_len = 0; | 591 | txhdr->wep_key_len = 0; |
605 | txhdr->frame_type = cpu_to_le32(control->queue + 4); | 592 | txhdr->frame_type = cpu_to_le32(info->queue + 4); |
606 | txhdr->magic4 = 0; | 593 | txhdr->magic4 = 0; |
607 | txhdr->antenna = (control->antenna_sel_tx == 0) ? | 594 | txhdr->antenna = (info->antenna_sel_tx == 0) ? |
608 | 2 : control->antenna_sel_tx - 1; | 595 | 2 : info->antenna_sel_tx - 1; |
609 | txhdr->output_power = 0x7f; // HW Maximum | 596 | txhdr->output_power = 0x7f; // HW Maximum |
610 | txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ? | 597 | txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
611 | 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); | 598 | 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); |
612 | if (padding) | 599 | if (padding) |
613 | txhdr->align[0] = padding; | 600 | txhdr->align[0] = padding; |
614 | 601 | ||
602 | /* modifies skb->cb and with it info, so must be last! */ | ||
603 | p54_assign_address(dev, skb, hdr, skb->len); | ||
604 | |||
615 | priv->tx(dev, hdr, skb->len, 0); | 605 | priv->tx(dev, hdr, skb->len, 0); |
616 | return 0; | 606 | return 0; |
617 | } | 607 | } |
@@ -634,7 +624,7 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, | |||
634 | filter = (struct p54_tx_control_filter *) hdr->data; | 624 | filter = (struct p54_tx_control_filter *) hdr->data; |
635 | hdr->magic1 = cpu_to_le16(0x8001); | 625 | hdr->magic1 = cpu_to_le16(0x8001); |
636 | hdr->len = cpu_to_le16(sizeof(*filter)); | 626 | hdr->len = cpu_to_le16(sizeof(*filter)); |
637 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL); | 627 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter)); |
638 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); | 628 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); |
639 | 629 | ||
640 | filter->filter_type = cpu_to_le16(filter_type); | 630 | filter->filter_type = cpu_to_le16(filter_type); |
@@ -678,7 +668,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
678 | hdr->magic1 = cpu_to_le16(0x8001); | 668 | hdr->magic1 = cpu_to_le16(0x8001); |
679 | hdr->len = cpu_to_le16(sizeof(*chan)); | 669 | hdr->len = cpu_to_le16(sizeof(*chan)); |
680 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); | 670 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); |
681 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL); | 671 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len); |
682 | 672 | ||
683 | chan->magic1 = cpu_to_le16(0x1); | 673 | chan->magic1 = cpu_to_le16(0x1); |
684 | chan->magic2 = cpu_to_le16(0x0); | 674 | chan->magic2 = cpu_to_le16(0x0); |
@@ -751,7 +741,7 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) | |||
751 | hdr->magic1 = cpu_to_le16(0x8001); | 741 | hdr->magic1 = cpu_to_le16(0x8001); |
752 | hdr->len = cpu_to_le16(sizeof(*led)); | 742 | hdr->len = cpu_to_le16(sizeof(*led)); |
753 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED); | 743 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED); |
754 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL); | 744 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led)); |
755 | 745 | ||
756 | led = (struct p54_tx_control_led *) hdr->data; | 746 | led = (struct p54_tx_control_led *) hdr->data; |
757 | led->mode = cpu_to_le16(mode); | 747 | led->mode = cpu_to_le16(mode); |
@@ -801,7 +791,7 @@ static void p54_set_vdcf(struct ieee80211_hw *dev) | |||
801 | 791 | ||
802 | hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; | 792 | hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; |
803 | 793 | ||
804 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL); | 794 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf)); |
805 | 795 | ||
806 | vdcf = (struct p54_tx_control_vdcf *) hdr->data; | 796 | vdcf = (struct p54_tx_control_vdcf *) hdr->data; |
807 | 797 | ||
@@ -837,12 +827,8 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
837 | { | 827 | { |
838 | struct p54_common *priv = dev->priv; | 828 | struct p54_common *priv = dev->priv; |
839 | struct sk_buff *skb; | 829 | struct sk_buff *skb; |
840 | while ((skb = skb_dequeue(&priv->tx_queue))) { | 830 | while ((skb = skb_dequeue(&priv->tx_queue))) |
841 | struct memrecord *range = (struct memrecord *)&skb->cb; | ||
842 | if (range->control) | ||
843 | kfree(range->control); | ||
844 | kfree_skb(skb); | 831 | kfree_skb(skb); |
845 | } | ||
846 | priv->stop(dev); | 832 | priv->stop(dev); |
847 | priv->mode = IEEE80211_IF_TYPE_INVALID; | 833 | priv->mode = IEEE80211_IF_TYPE_INVALID; |
848 | } | 834 | } |