struct p54_common *priv = dev->priv;
int i;
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+ return ;
+
for (i = 0; i < dev->queues; i++)
if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
ieee80211_wake_queue(dev, i);
}
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_tx_info *info;
+ struct memrecord *range;
+ unsigned long flags;
+ u32 freed = 0, last_addr = priv->rx_start;
+
+ if (!skb || !dev)
+ return;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *)info->rate_driver_data;
+ if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
+ struct ieee80211_tx_info *ni;
+ struct memrecord *mr;
+
+ ni = IEEE80211_SKB_CB(skb->prev);
+ mr = (struct memrecord *)ni->rate_driver_data;
+ last_addr = mr->end_addr;
+ }
+ if (skb->next != (struct sk_buff *)&priv->tx_queue) {
+ struct ieee80211_tx_info *ni;
+ struct memrecord *mr;
+
+ ni = IEEE80211_SKB_CB(skb->next);
+ mr = (struct memrecord *)ni->rate_driver_data;
+ freed = mr->start_addr - last_addr;
+ } else
+ freed = priv->rx_end - last_addr;
+ __skb_unlink(skb, &priv->tx_queue);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ kfree_skb(skb);
+
+ if (freed >= priv->headroom + sizeof(struct p54_control_hdr) + 48 +
+ IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+ p54_wake_free_queues(dev);
+}
+EXPORT_SYMBOL_GPL(p54_free_skb);
+
static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54_common *priv = dev->priv;
* marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
* allocated areas.
*/
-static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
+static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
struct p54_control_hdr *data, u32 len)
{
struct p54_common *priv = dev->priv;
struct sk_buff *entry = priv->tx_queue.next;
struct sk_buff *target_skb = NULL;
+ struct ieee80211_tx_info *info;
+ struct memrecord *range;
u32 last_addr = priv->rx_start;
u32 largest_hole = 0;
u32 target_addr = priv->rx_start;
unsigned int left;
len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
+ if (!skb)
+ return -EINVAL;
+
spin_lock_irqsave(&priv->tx_queue.lock, flags);
left = skb_queue_len(&priv->tx_queue);
while (left--) {
u32 hole_size;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
- struct memrecord *range = (void *)info->rate_driver_data;
+ info = IEEE80211_SKB_CB(entry);
+ range = (void *)info->rate_driver_data;
hole_size = range->start_addr - last_addr;
if (!target_skb && hole_size >= len) {
target_skb = entry->prev;
target_skb = priv->tx_queue.prev;
largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
if (!skb_queue_empty(&priv->tx_queue)) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb);
- struct memrecord *range = (void *)info->rate_driver_data;
+ info = IEEE80211_SKB_CB(target_skb);
+ range = (void *)info->rate_driver_data;
target_addr = range->end_addr;
}
} else
largest_hole = max(largest_hole, priv->rx_end - last_addr);
- if (skb) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct memrecord *range = (void *)info->rate_driver_data;
- range->start_addr = target_addr;
- range->end_addr = target_addr + len;
- __skb_queue_after(&priv->tx_queue, target_skb, skb);
- if (largest_hole < priv->rx_mtu + priv->headroom +
- priv->tailroom +
- sizeof(struct p54_control_hdr))
- ieee80211_stop_queues(dev);
+ if (!target_skb) {
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ ieee80211_stop_queues(dev);
+ return -ENOMEM;
}
+
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *)info->rate_driver_data;
+ range->start_addr = target_addr;
+ range->end_addr = target_addr + len;
+ __skb_queue_after(&priv->tx_queue, target_skb, skb);
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ if (largest_hole < priv->headroom + sizeof(struct p54_control_hdr) +
+ 48 + IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+ ieee80211_stop_queues(dev);
+
data->req_id = cpu_to_le32(target_addr + priv->headroom);
+ return 0;
+}
+
+static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev,
+ u16 hdr_flags, u16 len, u16 type, gfp_t memflags)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
+
+ skb = __dev_alloc_skb(len + priv->tx_hdr_len, memflags);
+ if (!skb)
+ return NULL;
+ skb_reserve(skb, priv->tx_hdr_len);
+
+ hdr = (struct p54_control_hdr *) skb_put(skb, sizeof(*hdr));
+ hdr->magic1 = cpu_to_le16(hdr_flags);
+ hdr->len = cpu_to_le16(len - sizeof(*hdr));
+ hdr->type = cpu_to_le16(type);
+ hdr->retry1 = hdr->retry2 = 0;
+
+ if (unlikely(p54_assign_address(dev, skb, hdr, len))) {
+ kfree_skb(skb);
+ return NULL;
+ }
+ return skb;
}
int p54_read_eeprom(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
struct p54_control_hdr *hdr = NULL;
struct p54_eeprom_lm86 *eeprom_hdr;
+ struct sk_buff *skb;
size_t eeprom_size = 0x2020, offset = 0, blocksize;
int ret = -ENOMEM;
void *eeprom = NULL;
- hdr = (struct p54_control_hdr *)kzalloc(sizeof(*hdr) +
- sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, 0x8000, sizeof(*hdr) + sizeof(*eeprom_hdr) +
+ EEPROM_READBACK_LEN,
+ P54_CONTROL_TYPE_EEPROM_READBACK, GFP_KERNEL);
+ if (!skb)
goto free;
-
priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
if (!priv->eeprom)
goto free;
-
eeprom = kzalloc(eeprom_size, GFP_KERNEL);
if (!eeprom)
goto free;
- hdr->magic1 = cpu_to_le16(0x8000);
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
- hdr->retry1 = hdr->retry2 = 0;
- eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+ eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
+ sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN);
while (eeprom_size) {
blocksize = min(eeprom_size, (size_t)EEPROM_READBACK_LEN);
- hdr->len = cpu_to_le16(blocksize + sizeof(*eeprom_hdr));
eeprom_hdr->offset = cpu_to_le16(offset);
eeprom_hdr->len = cpu_to_le16(blocksize);
- p54_assign_address(dev, NULL, hdr, le16_to_cpu(hdr->len) +
- sizeof(*hdr));
- priv->tx(dev, hdr, le16_to_cpu(hdr->len) + sizeof(*hdr), 0);
+ priv->tx(dev, skb, 0);
if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
printk(KERN_ERR "%s: device does not respond!\n",
free:
kfree(priv->eeprom);
priv->eeprom = NULL;
- kfree(hdr);
+ p54_free_skb(dev, skb);
kfree(eeprom);
return ret;
txhdr->align[0] = padding;
/* modifies skb->cb and with it info, so must be last! */
- p54_assign_address(dev, skb, hdr, skb->len);
-
- priv->tx(dev, hdr, skb->len, 0);
+ if (unlikely(p54_assign_address(dev, skb, hdr, skb->len))) {
+ skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
+ return NETDEV_TX_BUSY;
+ }
+ priv->tx(dev, skb, 0);
return 0;
}
const u8 *bssid)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
struct p54_tx_control_filter *filter;
- size_t data_len;
-
- hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
- priv->tx_hdr_len, GFP_ATOMIC);
- if (!hdr)
- return -ENOMEM;
+ u16 data_len = sizeof(struct p54_control_hdr) + sizeof(*filter);
- hdr = (void *)hdr + priv->tx_hdr_len;
+ if (priv->fw_var < 0x500)
+ data_len += P54_TX_CONTROL_FILTER_V1_LEN;
+ else
+ data_len += P54_TX_CONTROL_FILTER_V2_LEN;
- filter = (struct p54_tx_control_filter *) hdr->data;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
+ skb = p54_alloc_skb(dev, 0x8001, data_len, P54_CONTROL_TYPE_FILTER_SET,
+ GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
- priv->filter_type = filter->filter_type = cpu_to_le16(filter_type);
+ filter = (struct p54_tx_control_filter *) skb_put(skb, sizeof(*filter));
+ filter->filter_type = priv->filter_type = cpu_to_le16(filter_type);
memcpy(filter->mac_addr, priv->mac_addr, ETH_ALEN);
if (!bssid)
memset(filter->bssid, ~0, ETH_ALEN);
memcpy(filter->bssid, bssid, ETH_ALEN);
filter->rx_antenna = priv->rx_antenna;
if (priv->fw_var < 0x500) {
- data_len = P54_TX_CONTROL_FILTER_V1_LEN;
filter->v1.basic_rate_mask = cpu_to_le32(0x15f);
filter->v1.rx_addr = cpu_to_le32(priv->rx_end);
filter->v1.max_rx = cpu_to_le16(priv->rx_mtu);
filter->v1.rxhw = cpu_to_le16(priv->rxhw);
filter->v1.wakeup_timer = cpu_to_le16(500);
} else {
- data_len = P54_TX_CONTROL_FILTER_V2_LEN;
filter->v2.rx_addr = cpu_to_le32(priv->rx_end);
filter->v2.max_rx = cpu_to_le16(priv->rx_mtu);
filter->v2.rxhw = cpu_to_le16(priv->rxhw);
filter->v2.timer = cpu_to_le16(1000);
}
- hdr->len = cpu_to_le16(data_len);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
- priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+ priv->tx(dev, skb, 1);
return 0;
}
static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
struct p54_tx_control_channel *chan;
unsigned int i;
- size_t data_len;
+ size_t data_len = sizeof(struct p54_control_hdr) + sizeof(*chan);
void *entry;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, 0x8001, data_len,
+ P54_CONTROL_TYPE_CHANNEL_CHANGE, GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
-
- chan = (struct p54_tx_control_channel *) hdr->data;
-
- hdr->magic1 = cpu_to_le16(0x8001);
-
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
-
+ chan = (struct p54_tx_control_channel *) skb_put(skb, sizeof(*chan));
+ memset(chan->padding1, 0, sizeof(chan->padding1));
chan->flags = cpu_to_le16(0x1);
chan->dwell = cpu_to_le16(0x0);
chan->v1.rssical_mul = cpu_to_le16(130);
chan->v1.rssical_add = cpu_to_le16(0xfe70);
} else {
- data_len = P54_TX_CONTROL_CHANNEL_V2_LEN;
chan->v2.rssical_mul = cpu_to_le16(130);
chan->v2.rssical_add = cpu_to_le16(0xfe70);
chan->v2.basic_rate_mask = cpu_to_le32(0x15f);
}
-
- hdr->len = cpu_to_le16(data_len);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
- priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+ priv->tx(dev, skb, 1);
return 0;
err:
printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
- kfree(hdr);
+ kfree_skb(skb);
return -EINVAL;
}
static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
struct p54_tx_control_led *led;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, 0x8001, sizeof(*led) +
+ sizeof(struct p54_control_hdr),
+ P54_CONTROL_TYPE_LED, GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*led));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led));
-
- led = (struct p54_tx_control_led *) hdr->data;
+ led = (struct p54_tx_control_led *)skb_put(skb, sizeof(*led));
led->mode = cpu_to_le16(mode);
led->led_permanent = cpu_to_le16(link);
led->led_temporary = cpu_to_le16(act);
led->duration = cpu_to_le16(1000);
-
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
-
+ priv->tx(dev, skb, 1);
return 0;
}
static int p54_set_edcf(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
struct p54_edcf *edcf;
- hdr = kzalloc(priv->tx_hdr_len + sizeof(*hdr) + sizeof(*edcf),
- GFP_ATOMIC);
- if (!hdr)
+ skb = p54_alloc_skb(dev, 0x8001, sizeof(struct p54_control_hdr) +
+ sizeof(*edcf), P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*edcf));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
- hdr->retry1 = hdr->retry2 = 0;
- edcf = (struct p54_edcf *)hdr->data;
+ edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
if (priv->use_short_slot) {
edcf->slottime = 9;
edcf->sifs = 0x10;
edcf->round_trip_delay = cpu_to_le16(0);
memset(edcf->mapping, 0, sizeof(edcf->mapping));
memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
-
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*edcf));
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*edcf), 1);
+ priv->tx(dev, skb, 1);
return 0;
}
static int p54_init_stats(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_statistics *stats;
-
- priv->cached_stats = kzalloc(priv->tx_hdr_len +
- sizeof(*hdr) + sizeof(*stats), GFP_KERNEL);
+ priv->cached_stats = p54_alloc_skb(dev, 0x8000,
+ sizeof(struct p54_control_hdr) +
+ sizeof(struct p54_statistics),
+ P54_CONTROL_TYPE_STAT_READBACK,
+ GFP_KERNEL);
if (!priv->cached_stats)
return -ENOMEM;
- hdr = (void *) priv->cached_stats + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8000);
- hdr->len = cpu_to_le16(sizeof(*stats));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_STAT_READBACK);
- hdr->retry1 = hdr->retry2 = 0;
-
mod_timer(&priv->stats_timer, jiffies + HZ);
return 0;
}
struct sk_buff *skb;
del_timer(&priv->stats_timer);
- kfree(priv->cached_stats);
+ p54_free_skb(dev, priv->cached_stats);
priv->cached_stats = NULL;
while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);
+
priv->stop(dev);
priv->tsf_high32 = priv->tsf_low32 = 0;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
static int p54_init_xbow_synth(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
+ struct sk_buff *skb;
struct p54_tx_control_xbow_synth *xbow;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*xbow) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, 0x8001, sizeof(struct p54_control_hdr) +
+ sizeof(*xbow), P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
+ GFP_KERNEL);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*xbow));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_XBOW_SYNTH_CFG);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*xbow));
-
- xbow = (struct p54_tx_control_xbow_synth *) hdr->data;
+ xbow = (struct p54_tx_control_xbow_synth *)skb_put(skb, sizeof(*xbow));
xbow->magic1 = cpu_to_le16(0x1);
xbow->magic2 = cpu_to_le16(0x2);
xbow->freq = cpu_to_le16(5390);
-
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*xbow), 1);
-
+ memset(xbow->padding, 0, sizeof(xbow->padding));
+ priv->tx(dev, skb, 1);
return 0;
}
{
struct ieee80211_hw *dev = (struct ieee80211_hw *) data;
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_statistics *stats;
BUG_ON(!priv->cached_stats);
- hdr = (void *) priv->cached_stats + priv->tx_hdr_len;
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*stats));
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*stats), 0);
+ priv->tx(dev, priv->cached_stats, 0);
}
static int p54_get_stats(struct ieee80211_hw *dev,
void p54_free_common(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- kfree(priv->cached_stats);
+ del_timer(&priv->stats_timer);
+ kfree_skb(priv->cached_stats);
kfree(priv->iq_autocal);
kfree(priv->output_limit);
kfree(priv->curve_data);
usb_submit_urb(urb, GFP_ATOMIC);
}
+static void p54u_tx_reuse_skb_cb(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+ struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *)
+ usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
+
+ skb_pull(skb, priv->common.tx_hdr_len);
+ usb_free_urb(urb);
+}
+
static void p54u_tx_cb(struct urb *urb)
{
usb_free_urb(urb);
usb_free_urb(urb);
}
+static void p54u_tx_free_skb_cb(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+ struct ieee80211_hw *dev = (struct ieee80211_hw *)
+ usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+
+ p54_free_skb(dev, skb);
+ usb_free_urb(urb);
+}
+
static int p54u_init_urbs(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
}
}
-static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
+ int free_on_tx)
{
struct p54u_priv *priv = dev->priv;
struct urb *addr_urb, *data_urb;
}
usb_fill_bulk_urb(addr_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
- sizeof(data->req_id), p54u_tx_cb, dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ &((struct p54_control_hdr *)skb->data)->req_id, 4,
+ p54u_tx_cb, dev);
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len,
+ free_on_tx ? p54u_tx_free_skb_cb :
+ p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(addr_urb, GFP_ATOMIC);
usb_submit_urb(data_urb, GFP_ATOMIC);
return cpu_to_le32(chk);
}
-static void p54u_tx_lm87(struct ieee80211_hw *dev,
- struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
+ int free_on_tx)
{
struct p54u_priv *priv = dev->priv;
struct urb *data_urb;
- struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
+ struct lm87_tx_hdr *hdr;
+ __le32 checksum;
+ __le32 addr = ((struct p54_control_hdr *)skb->data)->req_id;
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb)
return;
- hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
- hdr->device_addr = data->req_id;
+ checksum = p54u_lm87_chksum((u32 *)skb->data, skb->len);
+ hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ hdr->chksum = checksum;
+ hdr->device_addr = addr;
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
- len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
- dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len,
+ free_on_tx ? p54u_tx_free_skb_cb :
+ p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(data_urb, GFP_ATOMIC);
}
-static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
+ int free_on_tx)
{
struct p54u_priv *priv = dev->priv;
struct urb *int_urb, *data_urb;
reg->addr = cpu_to_le32(P54U_DEV_BASE);
reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
- len += sizeof(*data);
- hdr = (void *)data - sizeof(*hdr);
+ hdr = (void *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
- hdr->device_addr = data->req_id;
- hdr->len = cpu_to_le16(len);
+ hdr->device_addr = ((struct p54_control_hdr *)skb->data)->req_id;
+ hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_control_hdr));
usb_fill_bulk_urb(int_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
usb_submit_urb(int_urb, GFP_ATOMIC);
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len,
+ free_on_tx ? p54u_tx_free_skb_cb :
+ p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(data_urb, GFP_ATOMIC);
}