修改的是kernel-2.6.30.-279中的mac80211驱动
因为在中断的下半部,只有工作队列才能休眠,写文件输入io操作,很有可能休眠,所以要把原来的tasklet修改为工作队列
mac80211/rx.c
-
void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
-
{
-
struct ieee80211_local *local = hw_to_local(hw);
-
-
BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
-
-
skb->pkt_type = IEEE80211_RX_MSG;
-
skb_queue_tail(&local->skb_queue, skb);
-
//tasklet_schedule(&local->tasklet);//原来是tasklet
-
schedule_work(&local->my_work);//现在使用工作队列
-
}
工作队列的处理函数
mac80211/main.c
-
char mac[6] = { 0xc0, 0xf2, 0xfb, 0x95, 0xb0, 0x50 };
-
struct pcap_hdr {
-
char Magic[4];
-
char Major[2];
-
char Minor[2];
-
char ThisZone[4];
-
char SigFigs[4];
-
char SnapLen[4];
-
char LinkType[4];
-
};
-
struct packet_hdr {
-
int Time1;
-
int Time2;
-
int Caplen;
-
int Len;
-
};
-
char radiotap[8];
-
struct pcap_hdr phdr = { .Magic = { 0xd4, 0xc3, 0xb2, 0xa1 }, .Major = { 0x02,
-
0x00 }, .Minor = { 0 }, .ThisZone = { 0 }, .SigFigs = { 0 }, .SnapLen =
-
{ 0xff, 0xff, 0x0, 0x0 }, .LinkType = { 0x7f, 0x0, 0x0, 0x0 }, };
-
-
static void ieee80211_my_work_handler(struct work_struct *work) {
-
struct ieee80211_local *local =container_of(work,struct ieee80211_local,my_work);
-
struct sta_info *sta, *tmp;
-
struct skb_eosp_msg_data *eosp_data;
-
struct sk_buff *skb;
-
-
while ((skb = skb_dequeue(&local->skb_queue)) || (skb = skb_dequeue(
-
&local->skb_queue_unreliable))) {
-
-
{
-
struct ieee80211_hdr *hdr;
-
//struct my_struct_t *my_name=container_of(work,struct my_struct_t,my_work);
-
hdr = (struct ieee80211_hdr *) (skb->data);
-
if (file == NULL) {
-
file = filp_open("/root/test.pcap",
-
O_RDWR | O_APPEND | O_CREAT, 0644);
-
old_fs = get_fs();
-
set_fs(KERNEL_DS);
-
pos = 0;
-
vfs_write(file, (char*) &phdr, sizeof(struct pcap_hdr), &pos);
-
set_fs(old_fs);
-
}
-
if (IS_ERR(file)) {
-
printk("error occured while opening file%s.\n",
-
"/root/test.pcap");
-
}
-
-
old_fs = get_fs();
-
set_fs(KERNEL_DS);
-
pos = 0;
-
struct packet_hdr pkt_hdr;
-
-
memset(&pkt_hdr, 0, sizeof(pkt_hdr));
-
pkt_hdr.Time1 = 0;
-
pkt_hdr.Time2 = 0;
-
pkt_hdr.Caplen = skb->len + 8;
-
pkt_hdr.Len = skb->len + 8;
-
printk("time1:%d\n", 0);
-
printk("time1:%d\n", 0);
-
printk("caplen:%d\n", pkt_hdr.Caplen);
-
printk("len:%d\n", pkt_hdr.Len);
-
printk("skb->pkt_type:%d\n", skb->pkt_type);
-
printk("skb->tstamp:%ld\n", skb->tstamp);
-
-
memset(radiotap, 0, sizeof(radiotap));
-
radiotap[2] = 0x08;
-
//vfs_write(file, (char*) &buf, strlen(buf), &pos);
-
//file->f_op->write(file,(char*)&buf,strlen(buf),&pos);
-
vfs_write(file, (char*) &pkt_hdr, sizeof(struct packet_hdr), &pos);
-
pos = 0;
-
vfs_write(file, (char*) &radiotap, 8, &pos);
-
pos = 0;
-
printk(KERN_ERR "addr1:%02x:%02x:%02x:%02x:%02x:%02x\t",hdr->addr1[0],hdr->addr1[1],hdr->addr1[2],hdr->addr1[3],hdr->addr1[4],hdr->addr1[5]);
-
printk(KERN_ERR "addr2:%02x:%02x:%02x:%02x:%02x:%02x\t",hdr->addr2[0],hdr->addr2[1],hdr->addr2[2],hdr->addr2[3],hdr->addr2[4],hdr->addr2[5]);
-
printk(KERN_ERR "addr3:%02x:%02x:%02x:%02x:%02x:%02x\n",hdr->addr3[0],hdr->addr3[1],hdr->addr3[2],hdr->addr3[3],hdr->addr3[4],hdr->addr3[5]);
-
vfs_write(file, (char*) hdr, skb->len, &pos);
-
set_fs(old_fs);
-
/*
-
if (file != NULL) {
-
filp_close(file, NULL);
-
file = NULL;
-
}
-
*/
-
}
-
-
switch (skb->pkt_type) {
-
case IEEE80211_RX_MSG:
-
/* Clear skb->pkt_type in order to not confuse kernel
-
* netstack. */
-
skb->pkt_type = 0;
-
//ieee80211_rx(local_to_hw(local), skb);
-
break;
-
case IEEE80211_TX_STATUS_MSG:
-
skb->pkt_type = 0;
-
ieee80211_tx_status(local_to_hw(local), skb);
-
break;
-
case IEEE80211_EOSP_MSG:
-
eosp_data = (void *) skb->cb;
-
for_each_sta_info(local, eosp_data->sta, sta, tmp)
-
{
-
/* skip wrong virtual interface */
-
if (memcmp(eosp_data->iface, sta->sdata->vif.addr, ETH_ALEN))
-
continue;
-
clear_sta_flag(sta, WLAN_STA_SP);
-
break;
-
}
-
dev_kfree_skb(skb);
-
break;
-
default:
-
WARN(1, "mac80211: Packet is of unknown type %d\n", skb->pkt_type);
-
dev_kfree_skb(skb);
-
break;
-
}
-
}
-
}
-
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
-
const struct ieee80211_ops *ops) {
-
-
struct ieee80211_local *local;
-
int priv_size, i;
-
struct wiphy *wiphy;
-
-
/* Ensure 32-byte alignment of our private data and hw private data.
-
* We use the wiphy priv data for both our ieee80211_local and for
-
* the driver's private data
-
*
-
* In memory it'll be like this:
-
*
-
* +-------------------------+
-
* | struct wiphy |
-
* +-------------------------+
-
* | struct ieee80211_local |
-
* +-------------------------+
-
* | driver's private data |
-
* +-------------------------+
-
*
-
*/
-
-
priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
-
-
wiphy = wiphy_new(&mac80211_config_ops, priv_size);
-
-
if (!wiphy)
-
return NULL;
-
-
wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
-
-
wiphy->privid = mac80211_wiphy_privid;
-
-
wiphy->flags |= WIPHY_FLAG_NETNS_OK | WIPHY_FLAG_4ADDR_AP
-
| WIPHY_FLAG_4ADDR_STATION;
-
-
if (!ops->set_key)
-
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-
-
wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
-
-
local = wiphy_priv(wiphy);
-
-
local->hw.wiphy = wiphy;
-
-
local->hw.priv = (char *) local + ALIGN(sizeof(*local), NETDEV_ALIGN);
-
-
BUG_ON(!ops->tx);
-
BUG_ON(!ops->start);
-
BUG_ON(!ops->stop);
-
BUG_ON(!ops->config);
-
BUG_ON(!ops->add_interface);
-
BUG_ON(!ops->remove_interface);
-
BUG_ON(!ops->configure_filter);
-
local->ops = ops;
-
-
/* set up some defaults */
-
local->hw.queues = 1;
-
local->hw.max_rates = 1;
-
local->hw.max_report_rates = 0;
-
local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
-
local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
-
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
-
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
-
local->user_power_level = -1;
-
local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
-
local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
-
-
INIT_LIST_HEAD(&local->interfaces);
-
mutex_init(&local->iflist_mtx);
-
mutex_init(&local->mtx);
-
-
mutex_init(&local->key_mtx);
-
spin_lock_init(&local->filter_lock);
-
spin_lock_init(&local->queue_stop_reason_lock);
-
-
/*
-
* The rx_skb_queue is only accessed from tasklets,
-
* but other SKB queues are used from within IRQ
-
* context. Therefore, this one needs a different
-
* locking class so our direct, non-irq-safe use of
-
* the queue's lock doesn't throw lockdep warnings.
-
*/
-
skb_queue_head_init_class(&local->rx_skb_queue,
-
&ieee80211_rx_skb_queue_class);
-
-
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
-
-
ieee80211_work_init(local);
-
-
INIT_WORK(&local->restart_work, ieee80211_restart_work);
-
-
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
-
INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
-
local->smps_mode = IEEE80211_SMPS_OFF;
-
-
INIT_WORK(&local->dynamic_ps_enable_work, ieee80211_dynamic_ps_enable_work);
-
INIT_WORK(&local->dynamic_ps_disable_work,
-
ieee80211_dynamic_ps_disable_work);
-
setup_timer(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer,
-
(unsigned long) local);
-
-
INIT_WORK(&local->sched_scan_stopped_work,
-
ieee80211_sched_scan_stopped_work);
-
-
sta_info_init(local);
-
-
for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
-
skb_queue_head_init(&local->pending[i]);
-
atomic_set(&local->agg_queue_stop[i], 0);
-
}
-
tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
-
(unsigned long) local);
-
-
tasklet_init(&local->tasklet, ieee80211_tasklet_handler,
-
(unsigned long) local);
-
INIT_WORK(&local->my_work, ieee80211_my_work_handler);//初始化工作队列
-
-
skb_queue_head_init(&local->skb_queue);
-
skb_queue_head_init(&local->skb_queue_unreliable);
-
-
/* init dummy netdev for use w/ NAPI */
-
init_dummy_netdev(&local->napi_dev);
-
-
ieee80211_led_names(local);
-
-
ieee80211_hw_roc_setup(local);
-
-
return local_to_hw(local);
-
}
重新加载一下驱动就可以
rmmod rtl8187
rmmod mac80211
insmod mac80211.ko
insmod /root/linux_module/rtl8187/rtl8187.ko
阅读(1318) | 评论(0) | 转发(0) |