channel->state == CH_STATE_UP)
qeth_issue_next_read(card);
- tasklet_schedule(&channel->irq_tasklet);
+ qeth_irq_tasklet((unsigned long)channel);
return;
out:
wake_up(&card->wait_q);
return 0;
}
-static inline int
+static int
__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
int same_type)
{
return rc;
}
-static inline void
+static void
__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
{
struct qeth_ipaddr *addr, *tmp;
static void qeth_add_multicast_ipv6(struct qeth_card *);
#endif
-static inline int
+static int
qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
{
unsigned long flags;
wake_up(&card->wait_q);
}
-static inline int
+static int
__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
{
unsigned long flags;
return rc;
}
-static int
-qeth_register_ip_addresses(void *ptr)
-{
- struct qeth_card *card;
-
- card = (struct qeth_card *) ptr;
- daemonize("qeth_reg_ip");
- QETH_DBF_TEXT(trace,4,"regipth1");
- if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))
- return 0;
- QETH_DBF_TEXT(trace,4,"regipth2");
- qeth_set_ip_addr_list(card);
- qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD);
- return 0;
-}
-
-/*
- * Drive the SET_PROMISC_MODE thread
- */
-static int
-qeth_set_promisc_mode(void *ptr)
-{
- struct qeth_card *card = (struct qeth_card *) ptr;
-
- daemonize("qeth_setprm");
- QETH_DBF_TEXT(trace,4,"setprm1");
- if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
- return 0;
- QETH_DBF_TEXT(trace,4,"setprm2");
- qeth_setadp_promisc_mode(card);
- qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
- return 0;
-}
-
static int
qeth_recover(void *ptr)
{
if (card->read.state != CH_STATE_UP &&
card->write.state != CH_STATE_UP)
return;
-
- if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
- kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
- if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
- kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
kernel_thread(qeth_recover, (void *) card, SIGCHLD);
}
card->options.layer2 = 1;
else
card->options.layer2 = 0;
- card->options.performance_stats = 1;
+ card->options.performance_stats = 0;
}
/**
return -ENOMEM;
}
qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
- wait_event(card->wait_q,
- atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(trace, 6, "noirqpnd");
rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
(addr_t) iob, 0, 0);
reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
if (reply){
atomic_set(&reply->refcnt, 1);
+ atomic_set(&reply->received, 0);
reply->card = card;
};
return reply;
kfree(reply);
}
-static void
-qeth_cmd_timeout(unsigned long data)
-{
- struct qeth_reply *reply, *list_reply, *r;
- unsigned long flags;
-
- reply = (struct qeth_reply *) data;
- spin_lock_irqsave(&reply->card->lock, flags);
- list_for_each_entry_safe(list_reply, r,
- &reply->card->cmd_waiter_list, list) {
- if (reply == list_reply){
- qeth_get_reply(reply);
- list_del_init(&reply->list);
- spin_unlock_irqrestore(&reply->card->lock, flags);
- reply->rc = -ETIME;
- reply->received = 1;
- wake_up(&reply->wait_q);
- qeth_put_reply(reply);
- return;
- }
- }
- spin_unlock_irqrestore(&reply->card->lock, flags);
-}
-
-
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
qeth_get_reply(reply);
reply->rc = -EIO;
- reply->received = 1;
+ atomic_inc(&reply->received);
list_del_init(&reply->list);
wake_up(&reply->wait_q);
qeth_put_reply(reply);
&card->cmd_waiter_list);
spin_unlock_irqrestore(&card->lock, flags);
} else {
- reply->received = 1;
+ atomic_inc(&reply->received);
wake_up(&reply->wait_q);
}
qeth_put_reply(reply);
qeth_release_buffer(channel,iob);
}
-static inline void
+static void
qeth_prepare_control_data(struct qeth_card *card, int len,
-struct qeth_cmd_buffer *iob)
+ struct qeth_cmd_buffer *iob)
{
qeth_setup_ccw(&card->write,iob->data,len);
iob->callback = qeth_release_buffer;
int rc;
unsigned long flags;
struct qeth_reply *reply = NULL;
- struct timer_list timer;
+ unsigned long timeout;
QETH_DBF_TEXT(trace, 2, "sendctl");
reply->seqno = QETH_IDX_COMMAND_SEQNO;
else
reply->seqno = card->seqno.ipa++;
- init_timer(&timer);
- timer.function = qeth_cmd_timeout;
- timer.data = (unsigned long) reply;
init_waitqueue_head(&reply->wait_q);
spin_lock_irqsave(&card->lock, flags);
list_add_tail(&reply->list, &card->cmd_waiter_list);
spin_unlock_irqrestore(&card->lock, flags);
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
- wait_event(card->wait_q,
- atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+
+ while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
qeth_prepare_control_data(card, len, iob);
+
if (IS_IPA(iob->data))
- timer.expires = jiffies + QETH_IPA_TIMEOUT;
+ timeout = jiffies + QETH_IPA_TIMEOUT;
else
- timer.expires = jiffies + QETH_TIMEOUT;
+ timeout = jiffies + QETH_TIMEOUT;
+
QETH_DBF_TEXT(trace, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
wake_up(&card->wait_q);
return rc;
}
- add_timer(&timer);
- wait_event(reply->wait_q, reply->received);
- del_timer_sync(&timer);
+ while (!atomic_read(&reply->received)) {
+ if (time_after(jiffies, timeout)) {
+ spin_lock_irqsave(&reply->card->lock, flags);
+ list_del_init(&reply->list);
+ spin_unlock_irqrestore(&reply->card->lock, flags);
+ reply->rc = -ETIME;
+ atomic_inc(&reply->received);
+ wake_up(&reply->wait_q);
+ }
+ };
rc = reply->rc;
qeth_put_reply(reply);
return rc;
return 0;
}
-static inline struct sk_buff *
+static struct sk_buff *
qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
{
struct sk_buff* skb;
return skb;
}
-static inline struct sk_buff *
+static struct sk_buff *
qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
struct qdio_buffer_element **__element, int *__offset,
struct qeth_hdr **hdr)
return NULL;
}
-static inline __be16
+static __be16
qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct qeth_card *card;
(card->info.link_type == QETH_LINK_TYPE_LANE_TR))
return tr_type_trans(skb,dev);
#endif /* CONFIG_TR */
- skb->mac.raw = skb->data;
+ skb_reset_mac_header(skb);
skb_pull(skb, ETH_HLEN );
eth = eth_hdr(skb);
return htons(ETH_P_802_2);
}
-static inline void
+static void
qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
struct iphdr *ip_hdr;
QETH_DBF_TEXT(trace,5,"skbfktr");
- skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR;
+ skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_TR);
/* this is a fake ethernet header */
- fake_hdr = (struct trh_hdr *) skb->mac.raw;
+ fake_hdr = tr_hdr(skb);
/* the destination MAC address */
switch (skb->pkt_type){
fake_llc->ethertype = ETH_P_IP;
}
-static inline void
+static void
qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
struct iphdr *ip_hdr;
QETH_DBF_TEXT(trace,5,"skbfketh");
- skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH;
+ skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_ETH);
/* this is a fake ethernet header */
- fake_hdr = (struct ethhdr *) skb->mac.raw;
+ fake_hdr = eth_hdr(skb);
/* the destination MAC address */
switch (skb->pkt_type){
qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
}
-static inline __u16
+static inline void
qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
- unsigned short vlan_id = 0;
-#ifdef CONFIG_QETH_VLAN
- struct vlan_hdr *vhdr;
-#endif
-
skb->pkt_type = PACKET_HOST;
skb->protocol = qeth_type_trans(skb, skb->dev);
if (card->options.checksum_type == NO_CHECKSUMMING)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
-#ifdef CONFIG_QETH_VLAN
- if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) {
- vhdr = (struct vlan_hdr *) skb->data;
- skb->protocol =
- __constant_htons(vhdr->h_vlan_encapsulated_proto);
- vlan_id = hdr->hdr.l2.vlan_id;
- skb_pull(skb, VLAN_HLEN);
- }
-#endif
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
- return vlan_id;
}
-static inline __u16
+static __u16
qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
if (card->options.fake_ll)
qeth_rebuild_skb_fake_ll(card, skb, hdr);
else
- skb->mac.raw = skb->data;
+ skb_reset_mac_header(skb);
skb->ip_summed = card->options.checksum_type;
if (card->options.checksum_type == HW_CHECKSUMMING){
if ( (hdr->hdr.l3.ext_flags &
return vlan_id;
}
-static inline void
+static void
qeth_process_inbound_buffer(struct qeth_card *card,
struct qeth_qdio_buffer *buf, int index)
{
int offset;
int rxrc;
__u16 vlan_tag = 0;
- __u16 *vlan_addr;
/* get first element of current buffer */
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
&offset, &hdr))) {
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
- vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
+ qeth_layer2_rebuild_skb(card, skb, hdr);
else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
vlan_tag = qeth_rebuild_skb(card, skb, hdr);
else { /*in case of OSN*/
skb_push(skb, sizeof(struct qeth_hdr));
- memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+ skb_copy_to_linear_data(skb, hdr,
+ sizeof(struct qeth_hdr));
}
/* is device UP ? */
if (!(card->dev->flags & IFF_UP)){
}
}
-static inline struct qeth_buffer_pool_entry *
+static struct qeth_buffer_pool_entry *
qeth_get_buffer_pool_entry(struct qeth_card *card)
{
struct qeth_buffer_pool_entry *entry;
return NULL;
}
-static inline void
+static void
qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
{
struct qeth_buffer_pool_entry *pool_entry;
buf->state = QETH_QDIO_BUF_EMPTY;
}
-static inline void
+static void
qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf)
{
atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
}
-static inline void
+static void
qeth_queue_input_buffer(struct qeth_card *card, int index)
{
struct qeth_qdio_q *queue = card->qdio.in_q;
card->perf_stats.inbound_start_time;
}
-static inline int
+static int
qeth_handle_send_error(struct qeth_card *card,
struct qeth_qdio_out_buffer *buffer,
unsigned int qdio_err, unsigned int siga_err)
* Switched to packing state if the number of used buffers on a queue
* reaches a certain limit.
*/
-static inline void
+static void
qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
{
if (!queue->do_pack) {
* In that case 1 is returned to inform the caller. If no buffer
* has to be flushed, zero is returned.
*/
-static inline int
+static int
qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
{
struct qeth_qdio_out_buffer *buffer;
* Checks if there is a packing buffer and prepares it to be flushed.
* In that case returns 1, otherwise zero.
*/
-static inline int
+static int
qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
{
struct qeth_qdio_out_buffer *buffer;
return 0;
}
-static inline void
+static void
qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
{
int index;
}
}
-static inline int
+static int
qeth_send_packet(struct qeth_card *, struct sk_buff *);
static int
return rc;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
- if (vg->vlan_devices[i] == dev){
+ if (vlan_group_get_device(vg, i) == dev){
rc = QETH_VLAN_CARD;
break;
}
return 0;
}
-static inline int
+static int
qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
}
/* try something else */
if (skb->protocol == ETH_P_IPV6)
- return (skb->nh.raw[24] == 0xff) ? RTN_MULTICAST : 0;
+ return (skb_network_header(skb)[24] == 0xff) ?
+ RTN_MULTICAST : 0;
else if (skb->protocol == ETH_P_IP)
- return ((skb->nh.raw[16] & 0xf0) == 0xe0) ? RTN_MULTICAST : 0;
+ return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+ RTN_MULTICAST : 0;
/* ... */
if (!memcmp(skb->data, skb->dev->broadcast, 6))
return RTN_BROADCAST;
return cast_type;
}
-static inline int
+static int
qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
int ipv, int cast_type)
{
return card->info.is_multicast_different &
(card->qdio.no_out_queues - 1);
if (card->qdio.do_prio_queueing && (ipv == 4)) {
+ const u8 tos = ip_hdr(skb)->tos;
+
if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
- if (skb->nh.iph->tos & IP_TOS_NOTIMPORTANT)
+ if (tos & IP_TOS_NOTIMPORTANT)
return 3;
- if (skb->nh.iph->tos & IP_TOS_HIGHRELIABILITY)
+ if (tos & IP_TOS_HIGHRELIABILITY)
return 2;
- if (skb->nh.iph->tos & IP_TOS_HIGHTHROUGHPUT)
+ if (tos & IP_TOS_HIGHTHROUGHPUT)
return 1;
- if (skb->nh.iph->tos & IP_TOS_LOWDELAY)
+ if (tos & IP_TOS_LOWDELAY)
return 0;
}
if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
- return 3 - (skb->nh.iph->tos >> 6);
+ return 3 - (tos >> 6);
} else if (card->qdio.do_prio_queueing && (ipv == 6)) {
/* TODO: IPv6!!! */
}
}
}
-static inline struct qeth_hdr *
+static struct qeth_hdr *
__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
{
#ifdef CONFIG_QETH_VLAN
* memcpys instead of one memmove to save cycles.
*/
skb_push(skb, VLAN_HLEN);
- memcpy(skb->data, skb->data + 4, 4);
- memcpy(skb->data + 4, skb->data + 8, 4);
- memcpy(skb->data + 8, skb->data + 12, 4);
+ skb_copy_to_linear_data(skb, skb->data + 4, 4);
+ skb_copy_to_linear_data_offset(skb, 4, skb->data + 8, 4);
+ skb_copy_to_linear_data_offset(skb, 8, skb->data + 12, 4);
tag = (u16 *)(skb->data + 12);
/*
* first two bytes = ETH_P_8021Q (0x8100)
qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
}
-static inline void
+static void
__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
{
if (orig_skb != new_skb)
dev_kfree_skb_any(new_skb);
}
-static inline struct sk_buff *
+static struct sk_buff *
qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr **hdr, int ipv)
{
- struct sk_buff *new_skb;
+ struct sk_buff *new_skb, *new_skb2;
QETH_DBF_TEXT(trace, 6, "prepskb");
-
- new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
- if (new_skb == NULL)
+ new_skb = skb;
+ new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+ if (!new_skb)
return NULL;
+ new_skb2 = qeth_realloc_headroom(card, new_skb,
+ sizeof(struct qeth_hdr));
+ if (!new_skb2) {
+ __qeth_free_new_skb(skb, new_skb);
+ return NULL;
+ }
+ if (new_skb != skb)
+ __qeth_free_new_skb(new_skb2, new_skb);
+ new_skb = new_skb2;
*hdr = __qeth_prepare_skb(card, new_skb, ipv);
if (*hdr == NULL) {
__qeth_free_new_skb(skb, new_skb);
return ct | QETH_CAST_UNICAST;
}
-static inline void
+static void
qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb)
{
}
}
-static inline void
+static void
qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int cast_type)
{
*((u32 *) skb->dst->neighbour->primary_key);
} else {
/* fill in destination address used in ip header */
- *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = skb->nh.iph->daddr;
+ *((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
+ ip_hdr(skb)->daddr;
}
} else if (ipv == 6) { /* IPv6 or passthru */
hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
skb->dst->neighbour->primary_key, 16);
} else {
/* fill in destination address used in ip header */
- memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16);
+ memcpy(hdr->hdr.l3.dest_addr,
+ &ipv6_hdr(skb)->daddr, 16);
}
} else { /* passthrough */
if((skb->dev->type == ARPHRD_IEEE802_TR) &&
}
}
-static inline void
+static void
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
int is_tso, int *next_element_to_fill)
{
*next_element_to_fill = element;
}
-static inline int
+static int
qeth_fill_buffer(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf,
struct sk_buff *skb)
return flush_cnt;
}
-static inline int
+static int
qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
int elements_needed,
return -EBUSY;
}
-static inline int
+static int
qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
int elements_needed, struct qeth_eddp_context *ctx)
return rc;
}
-static inline int
+static int
qeth_get_elements_no(struct qeth_card *card, void *hdr,
struct sk_buff *skb, int elems)
{
}
-static inline int
+static int
qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
{
int ipv = 0;
}
-static inline const char *
+static const char *
qeth_arp_get_error_cause(int *rc)
{
switch (*rc) {
return rc;
}
-static inline void
+static void
qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
struct qeth_arp_query_data *qdata,
int entry_size, int uentry_size)
"(0x%x/%d)\n",
QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
tmp, tmp);
- copy_to_user(udata, qinfo.udata, 4);
+ if (copy_to_user(udata, qinfo.udata, 4))
+ rc = -EFAULT;
} else {
- copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+ rc = -EFAULT;
}
kfree(qinfo.udata);
return rc;
if (rc)
PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
QETH_CARD_IFNAME(card), rc);
- else
- copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+ else {
+ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+ rc = -EFAULT;
+ }
kfree(ureq);
kfree(qinfo.udata);
spin_unlock_irqrestore(&card->vlanlock, flags);
}
-static inline void
+static void
qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
unsigned short vid)
{
QETH_DBF_TEXT(trace, 4, "frvaddr4");
rcu_read_lock();
- in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
+ in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
if (!in_dev)
goto out;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
QETH_DBF_TEXT(trace, 4, "frvaddr6");
- in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
+ in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
if (!in6_dev)
return;
for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
if (!card->vlangrp)
return;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- if (card->vlangrp->vlan_devices[i] == NULL)
+ if (vlan_group_get_device(card->vlangrp, i) == NULL)
continue;
if (clear)
qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
spin_lock_irqsave(&card->vlanlock, flags);
/* unregister IP addresses of vlan device */
qeth_free_vlan_addresses(card, vid);
- if (card->vlangrp)
- card->vlangrp->vlan_devices[vid] = NULL;
+ vlan_group_set_device(card->vlangrp, vid, NULL);
spin_unlock_irqrestore(&card->vlanlock, flags);
if (card->options.layer2)
qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
qeth_add_multicast_ipv6(card);
#endif
out:
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
return;
- if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_setadp_promisc_mode(card);
}
static int
spin_unlock_irqrestore(&card->ip_lock, flags);
}
-static inline void
+static void
qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
{
struct qeth_ipaddr *ipm;
vg = card->vlangrp;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- if (vg->vlan_devices[i] == NULL ||
- !(vg->vlan_devices[i]->flags & IFF_UP))
+ struct net_device *netdev = vlan_group_get_device(vg, i);
+ if (netdev == NULL ||
+ !(netdev->flags & IFF_UP))
continue;
- in_dev = in_dev_get(vg->vlan_devices[i]);
+ in_dev = in_dev_get(netdev);
if (!in_dev)
continue;
read_lock(&in_dev->mc_list_lock);
}
#ifdef CONFIG_QETH_IPV6
-static inline void
+static void
qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
{
struct qeth_ipaddr *ipm;
vg = card->vlangrp;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- if (vg->vlan_devices[i] == NULL ||
- !(vg->vlan_devices[i]->flags & IFF_UP))
+ struct net_device *netdev = vlan_group_get_device(vg, i);
+ if (netdev == NULL ||
+ !(netdev->flags & IFF_UP))
continue;
- in_dev = in6_dev_get(vg->vlan_devices[i]);
+ in_dev = in6_dev_get(netdev);
if (!in_dev)
continue;
read_lock(&in_dev->lock);
return rc;
}
-static inline void
+static void
qeth_fill_netmask(u8 *netmask, unsigned int len)
{
int i,j;
.set_tso = qeth_ethtool_set_tso,
};
+static int
+qeth_hard_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ struct qeth_card *card;
+ struct ethhdr *eth;
+
+ card = qeth_get_card_from_dev(skb->dev);
+ if (card->options.layer2)
+ goto haveheader;
+#ifdef CONFIG_QETH_IPV6
+ /* cause of the manipulated arp constructor and the ARP
+ flag for OSAE devices we have some nasty exceptions */
+ if (card->info.type == QETH_CARD_TYPE_OSAE) {
+ if (!card->options.fake_ll) {
+ if ((skb->pkt_type==PACKET_OUTGOING) &&
+ (skb->protocol==ETH_P_IPV6))
+ goto haveheader;
+ else
+ return 0;
+ } else {
+ if ((skb->pkt_type==PACKET_OUTGOING) &&
+ (skb->protocol==ETH_P_IP))
+ return 0;
+ else
+ goto haveheader;
+ }
+ }
+#endif
+ if (!card->options.fake_ll)
+ return 0;
+haveheader:
+ eth = eth_hdr(skb);
+ memcpy(haddr, eth->h_source, ETH_ALEN);
+ return ETH_ALEN;
+}
+
static int
qeth_netdev_init(struct net_device *dev)
{
if (card->options.fake_ll &&
(qeth_get_netdev_flags(card) & IFF_NOARP))
dev->hard_header = qeth_fake_header;
- dev->hard_header_parse = NULL;
+ if (dev->type == ARPHRD_IEEE802_TR)
+ dev->hard_header_parse = NULL;
+ else
+ dev->hard_header_parse = qeth_hard_header_parse;
dev->set_mac_address = qeth_layer2_set_mac_address;
dev->flags |= qeth_get_netdev_flags(card);
if ((card->options.fake_broadcast) ||
return rc;
}
-static inline int
+static int
qeth_setadapter_hstr(struct qeth_card *card)
{
int rc;
return rc;
}
-static inline int
+static int
qeth_start_ipa_arp_processing(struct qeth_card *card)
{
int rc;
wake_up(&card->wait_q);
}
-static inline int
+static int
qeth_threads_running(struct qeth_card *card, unsigned long threads)
{
unsigned long flags;
spin_unlock_irqrestore(&card->ip_lock, flags);
}
-static inline void
+static void
qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
{
int i, j;
}
if (!qeth_add_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
return rc;
}
return;
if (!qeth_delete_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
}
/*
}
if (!qeth_add_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
return 0;
}
return;
if (!qeth_delete_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
}
/**
default:
break;
}
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
out:
return NOTIFY_DONE;
}
default:
break;
}
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
out:
return NOTIFY_DONE;
}