1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96void volatile qeth_eyecatcher(void)
97{
98 return;
99}
100
101#include <linux/config.h>
102
103#ifndef CONFIG_CHANDEV
104#error "qeth can only be compiled with chandev support"
105#endif
106
107#include <linux/module.h>
108
109#include <linux/string.h>
110#include <linux/errno.h>
111#include <linux/mm.h>
112
113#include <linux/version.h>
114
115#include <asm/io.h>
116#include <asm/ebcdic.h>
117#include <linux/ctype.h>
118#include <asm/semaphore.h>
119#include <linux/if.h>
120#include <linux/if_arp.h>
121#include <linux/ip.h>
122#include <linux/inetdevice.h>
123#include <linux/netdevice.h>
124#include <linux/sched.h>
125#include <linux/kernel.h>
126#include <linux/slab.h>
127#include <linux/interrupt.h>
128#include <linux/tcp.h>
129#include <linux/icmp.h>
130#include <linux/skbuff.h>
131#ifdef CONFIG_PROC_FS
132#include <linux/proc_fs.h>
133#endif
134#include <net/route.h>
135#include <net/arp.h>
136#include <linux/in.h>
137#include <linux/igmp.h>
138#include <net/ip.h>
139#include <asm/uaccess.h>
140#include <linux/init.h>
141#include <net/ipv6.h>
142#include <linux/in6.h>
143#include <net/if_inet6.h>
144#include <net/addrconf.h>
145#include <linux/if_tr.h>
146#include <linux/trdevice.h>
147#include <linux/etherdevice.h>
148#include <linux/reboot.h>
149
150#include <linux/if_vlan.h>
151#include <asm/chandev.h>
152
153#include <asm/irq.h>
154#include <asm/s390dyn.h>
155#include <asm/debug.h>
156#include <asm/processor.h>
157
158#include <asm/qdio.h>
159
160#include "qeth_mpc.h"
161#include "qeth.h"
162
163
164static int qeth_sparebufs=0;
165MODULE_PARM(qeth_sparebufs,"i");
166MODULE_PARM_DESC(qeth_sparebufs,"the number of pre-allocated spare buffers " \
167 "reserved for low memory situations");
168
169static int global_stay_in_mem=0;
170
171
172#define VERSION_QETH_C "$Revision: 1.337.4.24 $"
173static const char *version="qeth S/390 OSA-Express driver (" \
174 VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
175 QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
176
177MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
178MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
179 "Copyright 2000,2003 IBM Corporation\n");
180MODULE_LICENSE("GPL");
181
182
183
184
185
186static qeth_card_t *firstcard=NULL;
187
188static sparebufs_t sparebufs[MAX_SPARE_BUFFERS];
189static int sparebuffer_count;
190
191static unsigned int known_devices[][10]=QETH_MODELLIST_ARRAY;
192
193static spinlock_t setup_lock;
194static rwlock_t list_lock=RW_LOCK_UNLOCKED;
195
196static debug_info_t *qeth_dbf_setup=NULL;
197static debug_info_t *qeth_dbf_data=NULL;
198static debug_info_t *qeth_dbf_misc=NULL;
199static debug_info_t *qeth_dbf_control=NULL;
200static debug_info_t *qeth_dbf_trace=NULL;
201static debug_info_t *qeth_dbf_sense=NULL;
202static debug_info_t *qeth_dbf_qerr=NULL;
203
204static int proc_file_registration;
205#ifdef QETH_PERFORMANCE_STATS
206static int proc_perf_file_registration;
207#define NOW qeth_get_micros()
208#endif
209static int proc_ipato_file_registration;
210
211static int ipato_inv4=0,ipato_inv6=0;
212static ipato_entry_t *ipato_entries=NULL;
213static spinlock_t ipato_list_lock;
214
215typedef struct {
216 char *data;
217 int len;
218} tempinfo_t;
219
220
221
222static int qeth_reinit_thread(void*);
223static inline void qeth_schedule_recovery(qeth_card_t *card);
224static int qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
225 unsigned short type, void *daddr, void *saddr,
226 unsigned len);
227
228static inline int QETH_IP_VERSION(struct sk_buff *skb)
229{
230 switch (skb->protocol) {
231 case ETH_P_IPV6: return 6;
232 case ETH_P_IP: return 4;
233 default: return 0;
234 }
235}
236
237static inline int qeth_min(int a,int b)
238{
239 if (a<b)
240 return a;
241 else
242 return b;
243}
244
245
246
247
248
249
250static inline struct sk_buff *qeth_pskb_unshare(struct sk_buff *skb, int pri)
251{
252 struct sk_buff *nskb;
253 if (!skb_cloned(skb))
254 return skb;
255 nskb = skb_copy(skb, pri);
256 kfree_skb(skb);
257 return nskb;
258}
259
260static inline unsigned int qeth_get_millis(void)
261{
262 __u64 time;
263
264 asm volatile ("STCK %0" : "=m" (time));
265 return (int) (time>>22);
266
267}
268
269#ifdef QETH_PERFORMANCE_STATS
270static inline unsigned int qeth_get_micros(void)
271{
272 __u64 time;
273
274 asm volatile ("STCK %0" : "=m" (time));
275 return (int) (time>>12);
276}
277#endif
278
279static void qeth_delay_millis(unsigned long msecs)
280{
281 unsigned int start;
282
283 start=qeth_get_millis();
284 while (qeth_get_millis()-start<msecs)
285 ;
286}
287
288static void qeth_wait_nonbusy(unsigned int timeout)
289{
290 unsigned int start;
291 char dbf_text[15];
292
293 sprintf(dbf_text,"wtnb%4x",timeout);
294 QETH_DBF_TEXT3(0,trace,dbf_text);
295
296 start=qeth_get_millis();
297 for (;;) {
298 set_task_state(current,TASK_INTERRUPTIBLE);
299 if (qeth_get_millis()-start>timeout) {
300 goto out;
301 }
302 schedule_timeout(((start+timeout-qeth_get_millis())>>10)*HZ);
303 }
304 out:
305 set_task_state(current,TASK_RUNNING);
306}
307
308static inline void qeth_get_mac_for_ipm(__u32 ipm,char *mac,
309 struct net_device *dev) {
310 if (dev->type==ARPHRD_IEEE802_TR)
311 ip_tr_mc_map(ipm,mac);
312 else
313 ip_eth_mc_map(ipm,mac);
314}
315
316#define HEXDUMP16(importance,header,ptr) \
317PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
318 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
319 *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
320 *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
321 *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
322 *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
323 *(((char*)ptr)+12),*(((char*)ptr)+13), \
324 *(((char*)ptr)+14),*(((char*)ptr)+15)); \
325PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
326 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
327 *(((char*)ptr)+16),*(((char*)ptr)+17), \
328 *(((char*)ptr)+18),*(((char*)ptr)+19), \
329 *(((char*)ptr)+20),*(((char*)ptr)+21), \
330 *(((char*)ptr)+22),*(((char*)ptr)+23), \
331 *(((char*)ptr)+24),*(((char*)ptr)+25), \
332 *(((char*)ptr)+26),*(((char*)ptr)+27), \
333 *(((char*)ptr)+28),*(((char*)ptr)+29), \
334 *(((char*)ptr)+30),*(((char*)ptr)+31));
335
336#define atomic_swap(a,b) xchg((int*)a.counter,b)
337
338#ifdef QETH_DBF_LIKE_HELL
339
340#define my_read_lock(x) do { \
341 void *ptr=x; \
342 QETH_DBF_TEXT6(0,trace,"rd_lck"); \
343 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
344 read_lock(x); \
345} while (0)
346#define my_read_unlock(x) do { \
347 void *ptr=x; \
348 QETH_DBF_TEXT6(0,trace,"rd_unlck"); \
349 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
350 read_unlock(x); \
351} while (0)
352#define my_write_lock(x) do { \
353 void *ptr=x; \
354 QETH_DBF_TEXT6(0,trace,"wr_lck"); \
355 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
356 write_lock(x); \
357} while (0)
358#define my_write_unlock(x) do { \
359 void *ptr=x; \
360 QETH_DBF_TEXT6(0,trace,"wr_unlck"); \
361 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
362 write_unlock(x); \
363} while (0)
364
365#define my_spin_lock(x) do { \
366 void *ptr=x; \
367 QETH_DBF_TEXT6(0,trace,"sp_lck"); \
368 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
369 spin_lock(x); \
370} while (0)
371#define my_spin_unlock(x) do { \
372 void *ptr=x; \
373 QETH_DBF_TEXT6(0,trace,"sp_unlck"); \
374 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
375 spin_unlock(x); \
376} while (0)
377#define my_spin_lock_irqsave(x,y) do { \
378 void *ptr=x; \
379 QETH_DBF_TEXT6(0,trace,"sp_lck_i"); \
380 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
381 spin_lock_irqsave(x,y); \
382} while (0)
383#define my_spin_unlock_irqrestore(x,y) do { \
384 void *ptr=x; \
385 QETH_DBF_TEXT6(0,trace,"sp_nlk_i"); \
386 QETH_DBF_HEX6(0,trace,&ptr,sizeof(void*)); \
387 spin_unlock_irqrestore(x,y); \
388} while (0)
389
390#else
391
392#define my_read_lock(x) read_lock(x)
393#define my_write_lock(x) write_lock(x)
394#define my_read_unlock(x) read_unlock(x)
395#define my_write_unlock(x) write_unlock(x)
396
397#define my_spin_lock(x) spin_lock(x)
398#define my_spin_unlock(x) spin_unlock(x)
399#define my_spin_lock_irqsave(x,y) spin_lock_irqsave(x,y)
400#define my_spin_unlock_irqrestore(x,y) spin_unlock_irqrestore(x,y)
401
402#endif
403
404static int inline my_spin_lock_nonbusy(qeth_card_t *card,spinlock_t *lock)
405{
406 for (;;) {
407 if (card) {
408 if (atomic_read(&card->shutdown_phase)) return -1;
409 }
410 if (spin_trylock(lock)) return 0;
411 qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME);
412 }
413}
414
415#ifdef CONFIG_ARCH_S390X
416#define QETH_GET_ADDR(x) ((__u32)(unsigned long)x)
417#else
418#define QETH_GET_ADDR(x) ((__u32)x)
419#endif
420
421static inline int qeth_does_card_exist(qeth_card_t *card)
422{
423 qeth_card_t *c=firstcard;
424 int rc=0;
425
426 my_read_lock(&list_lock);
427 while (c) {
428 if (c==card) {
429 rc=1;
430 break;
431 }
432 c=c->next;
433 }
434 my_read_unlock(&list_lock);
435 return rc;
436}
437
438static inline qeth_card_t *qeth_get_card_by_irq(int irq)
439{
440 qeth_card_t *card;
441
442 my_read_lock(&list_lock);
443 card=firstcard;
444 while (card) {
445 if ((card->irq0==irq)&&
446 (atomic_read(&card->shutdown_phase)!=
447 QETH_REMOVE_CARD_QUICK)) break;
448 if ((card->irq1==irq)&&
449 (atomic_read(&card->shutdown_phase)!=
450 QETH_REMOVE_CARD_QUICK)) break;
451 if ((card->irq2==irq)&&
452 (atomic_read(&card->shutdown_phase)!=
453 QETH_REMOVE_CARD_QUICK)) break;
454 card=card->next;
455 }
456 my_read_unlock(&list_lock);
457
458 return card;
459}
460
461static int qeth_getxdigit(char c)
462{
463 if ((c>='0') && (c<='9')) return c-'0';
464 if ((c>='a') && (c<='f')) return c+10-'a';
465 if ((c>='A') && (c<='F')) return c+10-'A';
466 return -1;
467}
468
469static qeth_card_t *qeth_get_card_by_name(char *name)
470{
471 qeth_card_t *card;
472
473 my_read_lock(&list_lock);
474 card=firstcard;
475 while (card) {
476 if (!strncmp(name,card->dev_name,DEV_NAME_LEN)) break;
477 card=card->next;
478 }
479 my_read_unlock(&list_lock);
480
481 return card;
482}
483
484static void qeth_convert_addr_to_text(int version,__u8 *addr,char *text)
485{
486 if (version==4) {
487 sprintf(text,"%02x%02x%02x%02x",
488 addr[0],addr[1],addr[2],addr[3]);
489 } else {
490 sprintf(text,"%02x%02x%02x%02x%02x%02x%02x%02x" \
491 "%02x%02x%02x%02x%02x%02x%02x%02x",
492 addr[0],addr[1],addr[2],addr[3],
493 addr[4],addr[5],addr[6],addr[7],
494 addr[8],addr[9],addr[10],addr[11],
495 addr[12],addr[13],addr[14],addr[15]);
496 }
497}
498
499static int qeth_convert_text_to_addr(int version,char *text,__u8 *addr)
500{
501 int olen=(version==4)?4:16;
502
503 while (olen--) {
504 if ( (!isxdigit(*text)) || (!isxdigit(*(text+1))) )
505 return -EINVAL;
506 *addr=(qeth_getxdigit(*text)<<4)+qeth_getxdigit(*(text+1));
507 addr++;
508 text+=2;
509 }
510 return 0;
511}
512
513static void qeth_add_ipato_entry(int version,__u8 *addr,int mask_bits,
514 char *dev_name)
515{
516 ipato_entry_t *entry,*e;
517 int len=(version==4)?4:16;
518
519 entry=(ipato_entry_t*)kmalloc(sizeof(ipato_entry_t),GFP_KERNEL);
520 if (!entry) {
521 PRINT_ERR("not enough memory for ipato allocation\n");
522 return;
523 }
524 entry->version=version;
525 memcpy(entry->addr,addr,len);
526 if (dev_name) {
527 strncpy(entry->dev_name,dev_name,DEV_NAME_LEN);
528 if (qeth_get_card_by_name(dev_name)->options.ena_ipat!=
529 ENABLE_TAKEOVER)
530 PRINT_WARN("IP takeover is not enabled on %s! " \
531 "Ignoring line\n",dev_name);
532 } else
533 memset(entry->dev_name,0,DEV_NAME_LEN);
534 entry->mask_bits=mask_bits;
535 entry->next=NULL;
536
537 my_spin_lock(&ipato_list_lock);
538 if (ipato_entries) {
539 e=ipato_entries;
540 while (e) {
541 if ( (e->version==version) &&
542 (e->mask_bits==mask_bits) &&
543 ( ((dev_name)&&!strncmp(e->dev_name,dev_name,
544 DEV_NAME_LEN)) ||
545 (!dev_name) ) &&
546 (!memcmp(e->addr,addr,len)) ) {
547 PRINT_INFO("ipato to be added does already " \
548 "exist\n");
549 kfree(entry);
550 goto out;
551 }
552 if (e->next) e=e->next; else break;
553 }
554 e->next=entry;
555 } else
556 ipato_entries=entry;
557out:
558 my_spin_unlock(&ipato_list_lock);
559}
560
561static void qeth_del_ipato_entry(int version,__u8 *addr,int mask_bits,
562 char *dev_name)
563{
564 ipato_entry_t *e,*e_before;
565 int len=(version==4)?4:16;
566 int found=0;
567
568 my_spin_lock(&ipato_list_lock);
569 e=ipato_entries;
570 if ( (e->version==version) &&
571 (e->mask_bits==mask_bits) &&
572 (!memcmp(e->addr,addr,len)) ) {
573 ipato_entries=e->next;
574 kfree(e);
575 } else while (e) {
576 e_before=e;
577 e=e->next;
578 if (!e) break;
579 if ( (e->version==version) &&
580 (e->mask_bits==mask_bits) &&
581 ( ((dev_name)&&!strncmp(e->dev_name,dev_name,
582 DEV_NAME_LEN)) ||
583 (!dev_name) ) &&
584 (!memcmp(e->addr,addr,len)) ) {
585 e_before->next=e->next;
586 kfree(e);
587 found=1;
588 break;
589 }
590 }
591 if (!found)
592 PRINT_INFO("ipato to be deleted does not exist\n");
593 my_spin_unlock(&ipato_list_lock);
594}
595
596static void qeth_convert_addr_to_bits(__u8 *addr,char *bits,int len)
597{
598 int i,j;
599 __u8 octet;
600
601 for (i=0;i<len;i++) {
602 octet=addr[i];
603 for (j=7;j>=0;j--) {
604 bits[i*8+j]=(octet&1)?1:0;
605 octet>>=1;
606 }
607 }
608}
609
610static int qeth_is_ipa_covered_by_ipato_entries(int version,__u8 *addr,
611 qeth_card_t *card)
612{
613 char *memarea,*addr_bits,*entry_bits;
614 int len=(version==4)?4:16;
615 int invert=(version==4)?ipato_inv4:ipato_inv6;
616 int result=0;
617 ipato_entry_t *e;
618
619 if (card->options.ena_ipat!=ENABLE_TAKEOVER) {
620 return 0;
621 }
622
623 memarea=kmalloc(256,GFP_KERNEL);
624 if (!memarea) {
625 PRINT_ERR("not enough memory to check out whether to " \
626 "use ipato\n");
627 return 0;
628 }
629 addr_bits=memarea;
630 entry_bits=memarea+128;
631 qeth_convert_addr_to_bits(addr,addr_bits,len);
632 e=ipato_entries;
633 while (e) {
634 qeth_convert_addr_to_bits(e->addr,entry_bits,len);
635 if ( (!memcmp(addr_bits,entry_bits,
636 __min(len*8,e->mask_bits))) &&
637 ( (e->dev_name[0]&&
638 (!strncmp(e->dev_name,card->dev_name,DEV_NAME_LEN))) ||
639 (!e->dev_name[0]) ) ) {
640 result=1;
641 break;
642 }
643 e=e->next;
644 }
645
646 kfree(memarea);
647 if (invert)
648 return !result;
649 else
650 return result;
651}
652
653static void qeth_set_dev_flag_running(qeth_card_t *card)
654{
655 if (card) {
656 card->dev->flags|=IFF_RUNNING;
657
658
659
660 }
661}
662
663static void qeth_set_dev_flag_norunning(qeth_card_t *card)
664{
665 if (card) {
666 card->dev->flags&=~IFF_RUNNING;
667
668
669
670 }
671}
672
673static void qeth_restore_dev_flag_state(qeth_card_t *card)
674{
675 if (card) {
676 if (card->saved_dev_flags&IFF_RUNNING)
677 card->dev->flags|=IFF_RUNNING;
678 else
679 card->dev->flags&=~IFF_RUNNING;
680
681
682
683
684
685
686 }
687}
688
689static void qeth_save_dev_flag_state(qeth_card_t *card)
690{
691 if (card) {
692 card->saved_dev_flags=card->dev->flags&IFF_RUNNING;
693
694
695
696 }
697}
698
699static inline int netif_is_busy(struct net_device *dev)
700{
701 return(test_bit(__LINK_STATE_XOFF,&dev->flags));
702}
703
704static int qeth_open(struct net_device *dev)
705{
706 char dbf_text[15];
707 qeth_card_t *card;
708
709 card=(qeth_card_t *)dev->priv;
710 sprintf(dbf_text,"open%4x",card->irq0);
711 QETH_DBF_TEXT2(0,trace,dbf_text);
712 QETH_DBF_TEXT2(0,setup,dbf_text);
713
714 qeth_save_dev_flag_state(card);
715
716 netif_start_queue(dev);
717 if (!atomic_swap(&((qeth_card_t*)dev->priv)->is_open,1)) {
718 MOD_INC_USE_COUNT;
719 }
720 return 0;
721}
722
723static int qeth_set_config(struct net_device *dev,struct ifmap *map)
724{
725 qeth_card_t *card=(qeth_card_t*)dev->priv;
726 char dbf_text[15];
727
728 sprintf(dbf_text,"nscf%04x",card->irq0);
729 QETH_DBF_TEXT3(0,trace,dbf_text);
730
731 return -EOPNOTSUPP;
732}
733
734static int qeth_is_multicast_skb_at_all(struct sk_buff *skb,int version)
735{
736 int i=RTN_UNSPEC;
737 qeth_card_t *card = (qeth_card_t *)skb->dev->priv;
738
739 if (skb->dst && skb->dst->neighbour) {
740 i=skb->dst->neighbour->type;
741 return ((i==RTN_BROADCAST)||
742 (i==RTN_MULTICAST)||
743 (i==RTN_ANYCAST))?i:0;
744 }
745
746 if (version==4) {
747 return ((skb->nh.raw[16]&0xf0)==0xe0)?RTN_MULTICAST:0;
748 } else if (version==6) {
749 return (skb->nh.raw[24]==0xff)?RTN_MULTICAST:0;
750 }
751 if (!memcmp(skb->nh.raw,skb->dev->broadcast,6)) {
752 i=RTN_BROADCAST;
753 } else {
754 __u16 hdr_mac;
755 hdr_mac=*((__u16*)skb->nh.raw);
756
757 switch (card->link_type) {
758 case QETH_MPC_LINK_TYPE_HSTR:
759 case QETH_MPC_LINK_TYPE_LANE_TR:
760 if ( (hdr_mac==QETH_TR_MAC_NC) ||
761 (hdr_mac==QETH_TR_MAC_C) )
762 i = RTN_MULTICAST;
763 break;
764
765 default:
766 if ( (hdr_mac==QETH_ETH_MAC_V4) ||
767 (hdr_mac==QETH_ETH_MAC_V6) )
768 i = RTN_MULTICAST;
769 }
770 }
771 return ((i==RTN_BROADCAST)||
772 (i==RTN_MULTICAST)||
773 (i==RTN_ANYCAST))?i:0;
774}
775
776static int qeth_get_prioqueue(qeth_card_t *card,struct sk_buff *skb,
777 int multicast,int version)
778{
779 if (!version &&
780 (card->type==QETH_CARD_TYPE_OSAE))
781 return QETH_DEFAULT_QUEUE;
782 switch (card->no_queues) {
783 case 1:
784 return 0;
785 case 4:
786 if ( (card->can_do_async_iqd) &&
787 (card->options.async_iqd==ASYNC_IQD) ) {
788 return card->no_queues-1;
789 }
790 if (card->is_multicast_different) {
791 if (multicast) {
792 return card->is_multicast_different&
793 (card->no_queues-1);
794 } else {
795 return 0;
796 }
797 }
798 if (card->options.do_prio_queueing) {
799 if (version==4) {
800 if (card->options.do_prio_queueing==
801 PRIO_QUEUEING_TOS) {
802 if (skb->nh.iph->tos&
803 IP_TOS_NOTIMPORTANT) {
804 return 3;
805 }
806 if (skb->nh.iph->tos&
807 IP_TOS_LOWDELAY) {
808 return 0;
809 }
810 if (skb->nh.iph->tos&
811 IP_TOS_HIGHTHROUGHPUT) {
812 return 1;
813 }
814 if (skb->nh.iph->tos&
815 IP_TOS_HIGHRELIABILITY) {
816 return 2;
817 }
818 return QETH_DEFAULT_QUEUE;
819 }
820 if (card->options.do_prio_queueing==
821 PRIO_QUEUEING_PREC) {
822 return 3-(skb->nh.iph->tos>>6);
823 }
824 } else if (version==6) {
825
826
827
828
829 }
830 return card->options.default_queue;
831 } else return card->options.default_queue;
832 default:
833 return 0;
834 }
835}
836
837static void qeth_wakeup(qeth_card_t *card) {
838 char dbf_text[15];
839
840 sprintf(dbf_text,"wkup%4x",card->irq0);
841 QETH_DBF_TEXT5(0,trace,dbf_text);
842
843 atomic_set(&card->data_has_arrived,1);
844 spin_lock(&card->wait_q_lock);
845 if (atomic_read(&card->wait_q_active)) {
846 wake_up(&card->wait_q);
847 }
848 spin_unlock(&card->wait_q_lock);
849}
850
851static int qeth_check_idx_response(unsigned char *buffer)
852{
853 if (!buffer)
854 return 0;
855 if ((buffer[2]&0xc0)==0xc0) {
856 return -EIO;
857 }
858 return 0;
859}
860
861static int qeth_get_cards_problem(qeth_card_t *card,unsigned char *buffer,
862 int irq,int dstat,int cstat,int rqparam,
863 char *irb,char *sense)
864{
865 char dbf_text[15];
866 int problem=0;
867
868 if (atomic_read(&card->shutdown_phase)) return 0;
869 if (dstat&DEV_STAT_UNIT_CHECK) {
870 if (irq==card->irq2) {
871 sprintf(dbf_text,"ACHK%04x",card->irq0);
872 QETH_DBF_TEXT1(0,trace,dbf_text);
873 problem=PROBLEM_ACTIVATE_CHECK_CONDITION;
874 goto out;
875 }
876 if (sense[SENSE_RESETTING_EVENT_BYTE]&
877 SENSE_RESETTING_EVENT_FLAG) {
878 sprintf(dbf_text,"REVN%04x",card->irq0);
879 QETH_DBF_TEXT1(0,trace,dbf_text);
880 problem=PROBLEM_RESETTING_EVENT_INDICATOR;
881 goto out;
882 }
883 if (sense[SENSE_COMMAND_REJECT_BYTE]&
884 SENSE_COMMAND_REJECT_FLAG) {
885 sprintf(dbf_text,"CREJ%04x",card->irq0);
886 QETH_DBF_TEXT1(0,trace,dbf_text);
887 problem=PROBLEM_COMMAND_REJECT;
888 goto out;
889 }
890 if ( (sense[2]==0xaf)&&(sense[3]==0xfe) ) {
891 sprintf(dbf_text,"AFFE%04x",card->irq0);
892 QETH_DBF_TEXT1(0,trace,dbf_text);
893 problem=PROBLEM_AFFE;
894 goto out;
895 }
896 if ( (!sense[0]) && (!sense[1]) &&
897 (!sense[2]) && (!sense[3]) ) {
898 sprintf(dbf_text,"ZSNS%04x",card->irq0);
899 QETH_DBF_TEXT1(0,trace,dbf_text);
900 problem=PROBLEM_ZERO_SENSE_DATA;
901 goto out;
902 }
903 sprintf(dbf_text,"GCHK%04x",card->irq0);
904 QETH_DBF_TEXT1(0,trace,dbf_text);
905 problem=PROBLEM_GENERAL_CHECK;
906 goto out;
907 }
908 if (cstat& (SCHN_STAT_CHN_CTRL_CHK|SCHN_STAT_INTF_CTRL_CHK|
909 SCHN_STAT_CHN_DATA_CHK|SCHN_STAT_CHAIN_CHECK|
910 SCHN_STAT_PROT_CHECK|SCHN_STAT_PROG_CHECK) ) {
911 sprintf(dbf_text,"GCHK%04x",card->irq0);
912 QETH_DBF_TEXT1(0,trace,dbf_text);
913 QETH_DBF_HEX1(0,misc,irb,__max(QETH_DBF_MISC_LEN,64));
914 PRINT_WARN("check on irq x%x, dstat=x%x, cstat=x%x, " \
915 "rqparam=x%x\n",irq,dstat,cstat,rqparam);
916 HEXDUMP16(WARN,"irb: ",irb);
917 HEXDUMP16(WARN,"irb: ",((char*)irb)+32);
918 problem=PROBLEM_GENERAL_CHECK;
919 goto out;
920 }
921 if (qeth_check_idx_response(buffer)) {
922 PRINT_WARN("received an IDX TERMINATE on irq 0x%X/0x%X " \
923 "with cause code 0x%02x%s\n",
924 card->irq0,card->irq1,buffer[4],
925 (buffer[4]==0x22)?" -- try another portname":"");
926 sprintf(dbf_text,"RTRM%04x",card->irq0);
927 QETH_DBF_TEXT1(0,trace,dbf_text);
928 problem=PROBLEM_RECEIVED_IDX_TERMINATE;
929 goto out;
930 }
931 if (IS_IPA(buffer) && !IS_IPA_REPLY(buffer)) {
932 if ( *(PDU_ENCAPSULATION(buffer))==IPA_CMD_STOPLAN ) {
933 atomic_set(&card->is_startlaned,0);
934
935
936
937 PRINT_WARN("Link failure on %s (CHPID 0x%X) -- " \
938 "there is a network problem or someone " \
939 "pulled the cable or disabled the port."
940 "Discarding outgoing packets.\n",
941 card->dev_name,card->chpid);
942 sprintf(dbf_text,"CBOT%04x",card->irq0);
943 QETH_DBF_TEXT1(0,trace,dbf_text);
944 qeth_set_dev_flag_norunning(card);
945 problem=0;
946 goto out;
947 }
948
949 if ( *(PDU_ENCAPSULATION(buffer))==IPA_CMD_STARTLAN ) {
950 if (!atomic_read(&card->is_startlaned)) {
951 atomic_set(&card->is_startlaned,1);
952 problem=PROBLEM_CARD_HAS_STARTLANED;
953 }
954 goto out;
955 }
956 if ( *(PDU_ENCAPSULATION(buffer))==
957 IPA_CMD_REGISTER_LOCAL_ADDR ) {
958 sprintf(dbf_text,"irla%04x",card->irq0);
959 QETH_DBF_TEXT3(0,trace,dbf_text);
960 }
961 if ( *(PDU_ENCAPSULATION(buffer))==
962 IPA_CMD_UNREGISTER_LOCAL_ADDR ) {
963 sprintf(dbf_text,"irla%04x",card->irq0);
964 QETH_DBF_TEXT3(0,trace,dbf_text);
965 }
966 PRINT_WARN("probably a problem on %s: received data is " \
967 "IPA, but not a reply: command=0x%x\n",
968 card->dev_name,*(PDU_ENCAPSULATION(buffer)+1));
969 sprintf(dbf_text,"INRP%04x",card->irq0);
970 QETH_DBF_TEXT1(0,trace,dbf_text);
971 goto out;
972 }
973
974out:
975 if (problem) {
976 sprintf(dbf_text,"gcpr%4x",card->irq0);
977 QETH_DBF_TEXT3(0,trace,dbf_text);
978 sprintf(dbf_text,"%2x%2x%4x",dstat,cstat,problem);
979 QETH_DBF_TEXT3(0,trace,dbf_text);
980 sprintf(dbf_text,"%8x",rqparam);
981 QETH_DBF_TEXT3(0,trace,dbf_text);
982 if (buffer)
983 QETH_DBF_HEX3(0,trace,&buffer,sizeof(void*));
984 QETH_DBF_HEX3(0,trace,&irb,sizeof(void*));
985 QETH_DBF_HEX3(0,trace,&sense,sizeof(void*));
986 }
987 atomic_set(&card->problem,problem);
988 return problem;
989}
990
991
992static void qeth_issue_next_read(qeth_card_t *card)
993{
994 int result,result2;
995 char dbf_text[15];
996
997 sprintf(dbf_text,"isnr%04x",card->irq0);
998 QETH_DBF_TEXT5(0,trace,dbf_text);
999
1000
1001 memcpy(&card->dma_stuff->read_ccw,READ_CCW,sizeof(ccw1_t));
1002 card->dma_stuff->read_ccw.count=QETH_BUFSIZE;
1003
1004 card->dma_stuff->read_ccw.cda=QETH_GET_ADDR(card->dma_stuff->recbuf);
1005
1006
1007
1008 result=do_IO(card->irq0,&card->dma_stuff->read_ccw,
1009 MPC_SETUP_STATE,0,0);
1010 if (result) {
1011 qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
1012 result2=do_IO(card->irq0,&card->dma_stuff->read_ccw,
1013 MPC_SETUP_STATE,0,0);
1014 PRINT_WARN("read handler on irq x%x, read: do_IO " \
1015 "returned %i, next try returns %i\n",
1016 card->irq0,result,result2);
1017 sprintf(dbf_text,"IsNR%04x",card->irq0);
1018 QETH_DBF_TEXT1(0,trace,dbf_text);
1019 sprintf(dbf_text,"%04x%04x",(__s16)result,(__s16)result2);
1020 QETH_DBF_TEXT1(0,trace,dbf_text);
1021 }
1022}
1023
1024static int qeth_is_to_recover(qeth_card_t *card,int problem)
1025{
1026 switch (problem) {
1027 case PROBLEM_CARD_HAS_STARTLANED:
1028 return 1;
1029 case PROBLEM_RECEIVED_IDX_TERMINATE:
1030 if (atomic_read(&card->in_recovery)) {
1031 return 1;
1032 } else {
1033 qeth_set_dev_flag_norunning(card);
1034 return 0;
1035 }
1036 case PROBLEM_ACTIVATE_CHECK_CONDITION:
1037 return 1;
1038 case PROBLEM_RESETTING_EVENT_INDICATOR:
1039 return 1;
1040 case PROBLEM_COMMAND_REJECT:
1041 return 0;
1042 case PROBLEM_ZERO_SENSE_DATA:
1043 return 0;
1044 case PROBLEM_GENERAL_CHECK:
1045 return 1;
1046 case PROBLEM_BAD_SIGA_RESULT:
1047 return 1;
1048 case PROBLEM_USER_TRIGGERED_RECOVERY:
1049 return 1;
1050 case PROBLEM_AFFE:
1051 return 1;
1052 case PROBLEM_MACHINE_CHECK:
1053 return 1;
1054 case PROBLEM_TX_TIMEOUT:
1055 return 1;
1056 }
1057 return 0;
1058}
1059
1060static int qeth_wait_for_event(atomic_t *var,unsigned int timeout)
1061{
1062 unsigned int start;
1063 int retval;
1064 char dbf_text[15];
1065
1066 QETH_DBF_TEXT5(0,trace,"wait4evn");
1067 sprintf(dbf_text,"%08x",timeout);
1068 QETH_DBF_TEXT5(0,trace,dbf_text);
1069 QETH_DBF_HEX5(0,trace,&var,sizeof(void*));
1070
1071 start=qeth_get_millis();
1072 for (;;) {
1073 set_task_state(current,TASK_INTERRUPTIBLE);
1074 if (atomic_read(var)) {
1075 retval=0;
1076 goto out;
1077 }
1078 if (qeth_get_millis()-start>timeout) {
1079 retval=-ETIME;
1080 goto out;
1081 }
1082 schedule_timeout(((start+timeout-qeth_get_millis())>>10)*HZ);
1083 }
1084 out:
1085 set_task_state(current,TASK_RUNNING);
1086
1087 return retval;
1088}
1089
1090static inline int qeth_get_spare_buf(void)
1091{
1092 int i=0;
1093 char dbf_text[15];
1094
1095 while (i<sparebuffer_count) {
1096 if (!atomic_compare_and_swap(SPAREBUF_FREE,SPAREBUF_USED,
1097 &sparebufs[i].status)) {
1098 sprintf(dbf_text,"gtspb%3x",i);
1099 QETH_DBF_TEXT4(0,trace,dbf_text);
1100 return i;
1101 }
1102 i++;
1103 }
1104 QETH_DBF_TEXT3(0,trace,"nospbuf");
1105
1106 return -1;
1107}
1108
1109static void qeth_put_spare_buf(int no)
1110{
1111 char dbf_text[15];
1112
1113 sprintf(dbf_text,"ptspb%3x",no);
1114 QETH_DBF_TEXT4(0,trace,dbf_text);
1115 atomic_set(&sparebufs[no].status, SPAREBUF_FREE);
1116}
1117
1118static inline void qeth_put_buffer_pool_entry(qeth_card_t *card,int entry_no)
1119{
1120 if (entry_no&SPAREBUF_MASK)
1121 qeth_put_spare_buf(entry_no&(~SPAREBUF_MASK));
1122 else
1123 card->inbound_buffer_pool_entry_used[entry_no]=BUFFER_UNUSED;
1124}
1125
1126static inline int qeth_get_empty_buffer_pool_entry(qeth_card_t *card)
1127{
1128 int i;
1129 int max_buffers=card->options.inbound_buffer_count;
1130
1131 for (i=0;i<max_buffers;i++) {
1132 if (xchg((int*)&card->inbound_buffer_pool_entry_used[i],
1133 BUFFER_USED)==BUFFER_UNUSED) return i;
1134 }
1135 return -1;
1136}
1137
1138static inline void qeth_clear_input_buffer(qeth_card_t *card,int bufno)
1139{
1140 qdio_buffer_t *buffer;
1141 int i;
1142 int elements,el_m_1;
1143 void *ptr;
1144#ifdef QETH_DBF_LIKE_HELL
1145 char dbf_text[15];
1146
1147 sprintf(dbf_text,"clib%4x",card->irq0);
1148 QETH_DBF_TEXT6(0,trace,dbf_text);
1149 sprintf(dbf_text,"bufno%3x",bufno);
1150 QETH_DBF_TEXT6(0,trace,dbf_text);
1151#endif
1152
1153 buffer=&card->inbound_qdio_buffers[bufno];
1154 elements=BUFFER_MAX_ELEMENTS;
1155 el_m_1=elements-1;
1156
1157 for (i=0;i<elements;i++) {
1158 if (i==el_m_1)
1159 buffer->element[i].flags=SBAL_FLAGS_LAST_ENTRY;
1160 else
1161 buffer->element[i].flags=0;
1162
1163 buffer->element[i].length=PAGE_SIZE;
1164 ptr=INBOUND_BUFFER_POS(card,bufno,i);
1165 if (card->do_pfix) {
1166
1167 buffer->element[i].addr=(void *)pfix_get_page_addr(ptr);
1168 card->real_inb_buffer_addr[bufno][i]=ptr;
1169 } else {
1170 buffer->element[i].addr=ptr;
1171 }
1172 }
1173}
1174
1175static inline void qeth_queue_input_buffer(qeth_card_t *card,int bufno,
1176 unsigned int under_int)
1177{
1178 int count=0,start=0,stop=0,pos;
1179 int result;
1180 int cnt1,cnt2=0;
1181 int wrapped=0;
1182 int i;
1183 int requeue_counter;
1184 char dbf_text[15];
1185 int no;
1186
1187#ifdef QETH_DBF_LIKE_HELL
1188 sprintf(dbf_text,"qibf%4x",card->irq0);
1189 QETH_DBF_TEXT5(0,trace,dbf_text);
1190 sprintf(dbf_text,"%4x%4x",under_int,bufno);
1191 QETH_DBF_TEXT5(0,trace,dbf_text);
1192#endif
1193 atomic_inc(&card->requeue_counter);
1194 if (atomic_read(&card->requeue_counter) > QETH_REQUEUE_THRESHOLD) {
1195 if (!spin_trylock(&card->requeue_input_lock)) {
1196#ifndef QETH_DBF_LIKE_HELL
1197 sprintf(dbf_text,"qibl%4x",card->irq0);
1198 QETH_DBF_TEXT5(0,trace,dbf_text);
1199#endif
1200 return;
1201 }
1202 requeue_counter=atomic_read(&card->requeue_counter);
1203 pos=atomic_read(&card->requeue_position);
1204
1205 start=pos;
1206
1207
1208
1209
1210 while ( (!atomic_read(&card->inbound_buffer_refcnt[pos])) &&
1211 (count<requeue_counter-1) ) {
1212 no=qeth_get_empty_buffer_pool_entry(card);
1213 if (no==-1) {
1214 if (count) break;
1215 no=qeth_get_spare_buf();
1216 if (no==-1) {
1217 PRINT_ERR("%s: no more input "\
1218 "buffers available! " \
1219 "Inbound traffic could " \
1220 "be lost! Try to spend " \
1221 "more memory for qeth\n",
1222 card->dev_name);
1223 sprintf(dbf_text,"QINB%4x",card->irq0);
1224 QETH_DBF_TEXT2(1,trace,dbf_text);
1225 goto out;
1226 }
1227 card->inbound_buffer_entry_no[pos]=
1228 no|SPAREBUF_MASK;
1229 }
1230 card->inbound_buffer_entry_no[pos]=no;
1231 atomic_set(&card->inbound_buffer_refcnt[pos],1);
1232 count++;
1233 if (pos>=QDIO_MAX_BUFFERS_PER_Q-1) {
1234 pos=0;
1235 wrapped=1;
1236 } else pos++;
1237 }
1238
1239 stop=pos;
1240
1241#ifdef QETH_DBF_LIKE_HELL
1242 sprintf(dbf_text,"qibi%4x",card->irq0);
1243 QETH_DBF_TEXT3(0,trace,dbf_text);
1244 sprintf(dbf_text,"%4x",requeue_counter);
1245 QETH_DBF_TEXT3(0,trace,dbf_text);
1246 sprintf(dbf_text,"%4x%4x",start,stop);
1247 QETH_DBF_TEXT3(0,trace,dbf_text);
1248#endif
1249 if (wrapped) {
1250 cnt1=QDIO_MAX_BUFFERS_PER_Q-start;
1251 cnt2=stop;
1252 } else {
1253 cnt1=count;
1254
1255 }
1256
1257 atomic_sub(count,&card->requeue_counter);
1258
1259
1260 atomic_set(&card->requeue_position,
1261 (atomic_read(&card->requeue_position)+count)
1262 &(QDIO_MAX_BUFFERS_PER_Q-1));
1263
1264 if (cnt1) {
1265 for (i=start;i<start+cnt1;i++) {
1266 qeth_clear_input_buffer(card,i);
1267 }
1268 result=do_QDIO(card->irq2,
1269 QDIO_FLAG_SYNC_INPUT|under_int,
1270 0,start,cnt1,
1271 NULL);
1272 if (result) {
1273 PRINT_WARN("qeth_queue_input_buffer's " \
1274 "do_QDIO returnd %i " \
1275 "(irq 0x%x)\n",
1276 result,card->irq2);
1277 sprintf(dbf_text,"QIDQ%4x",card->irq0);
1278 QETH_DBF_TEXT1(0,trace,dbf_text);
1279 sprintf(dbf_text,"%4x%4x",result,
1280 requeue_counter);
1281 QETH_DBF_TEXT1(0,trace,dbf_text);
1282 sprintf(dbf_text,"%4x%4x",start,cnt1);
1283 QETH_DBF_TEXT1(1,trace,dbf_text);
1284 }
1285 }
1286 if (cnt2) {
1287 for (i=0;i<cnt2;i++) {
1288 qeth_clear_input_buffer(card,i);
1289 }
1290 result=do_QDIO(card->irq2,
1291 QDIO_FLAG_SYNC_INPUT|under_int,0,
1292 0,cnt2,
1293 NULL);
1294 if (result) {
1295 PRINT_WARN("qeth_queue_input_buffer's " \
1296 "do_QDIO returnd %i " \
1297 "(irq 0x%x)\n",
1298 result,card->irq2);
1299 sprintf(dbf_text,"QIDQ%4x",card->irq0);
1300 QETH_DBF_TEXT1(0,trace,dbf_text);
1301 sprintf(dbf_text,"%4x%4x",result,
1302 requeue_counter);
1303 QETH_DBF_TEXT1(0,trace,dbf_text);
1304 sprintf(dbf_text,"%4x%4x",0,cnt2);
1305 QETH_DBF_TEXT1(1,trace,dbf_text);
1306 }
1307 }
1308out:
1309 my_spin_unlock(&card->requeue_input_lock);
1310 }
1311
1312}
1313
1314static inline struct sk_buff *qeth_get_skb(unsigned int len)
1315{
1316 struct sk_buff *skb;
1317
1318#ifdef QETH_VLAN
1319 skb=dev_alloc_skb(len+VLAN_HLEN);
1320 if (skb) skb_reserve(skb,VLAN_HLEN);
1321#else
1322 skb=dev_alloc_skb(len);
1323#endif
1324 return skb;
1325}
1326
1327static inline struct sk_buff *qeth_get_next_skb(qeth_card_t *card,
1328 int *element_ptr,
1329 int *pos_in_el_ptr,
1330 void **hdr_ptr,
1331 qdio_buffer_t *buffer)
1332{
1333 int length;
1334 char *data_ptr;
1335 int step,len_togo,element,pos_in_el;
1336 int curr_len;
1337 int max_elements;
1338 struct sk_buff *skb;
1339 char dbf_text[15];
1340
1341 max_elements=BUFFER_MAX_ELEMENTS;
1342
1343#define SBALE_LEN(x) ((x>=max_elements)?0:(buffer->element[x].length))
1344#define SBALE_ADDR(x) (buffer->element[x].addr)
1345
1346 element=*element_ptr;
1347
1348 if (element>=max_elements) {
1349 PRINT_WARN("irq 0x%x: error in interpreting buffer (data " \
1350 "too long), %i elements.\n",card->irq0,element);
1351 sprintf(dbf_text,"IEDL%4x",card->irq0);
1352 QETH_DBF_TEXT0(0,trace,dbf_text);
1353 sprintf(dbf_text,"%4x%4x",*element_ptr,*pos_in_el_ptr);
1354 QETH_DBF_TEXT0(1,trace,dbf_text);
1355 QETH_DBF_HEX0(0,misc,buffer,QETH_DBF_MISC_LEN);
1356 QETH_DBF_HEX0(0,misc,buffer+QETH_DBF_MISC_LEN,
1357 QETH_DBF_MISC_LEN);
1358 return NULL;
1359 }
1360
1361 pos_in_el=*pos_in_el_ptr;
1362
1363 curr_len=SBALE_LEN(element);
1364 if (curr_len>PAGE_SIZE) {
1365 PRINT_WARN("irq 0x%x: bad element length in element %i: " \
1366 "0x%x\n",card->irq0,element,curr_len);
1367 sprintf(dbf_text,"BELN%4x",card->irq0);
1368 QETH_DBF_TEXT0(0,trace,dbf_text);
1369 sprintf(dbf_text,"%4x",curr_len);
1370 QETH_DBF_TEXT0(0,trace,dbf_text);
1371 sprintf(dbf_text,"%4x%4x",*element_ptr,*pos_in_el_ptr);
1372 QETH_DBF_TEXT0(1,trace,dbf_text);
1373 QETH_DBF_HEX0(0,misc,buffer,QETH_DBF_MISC_LEN);
1374 QETH_DBF_HEX0(0,misc,buffer+QETH_DBF_MISC_LEN,
1375 QETH_DBF_MISC_LEN);
1376 return NULL;
1377 }
1378
1379 if (curr_len<pos_in_el+QETH_HEADER_SIZE) {
1380 if (!pos_in_el) {
1381#ifdef QETH_DBF_LIKE_HELL
1382 sprintf(dbf_text,"gnmh%4x",card->irq0);
1383 QETH_DBF_TEXT6(0,trace,dbf_text);
1384#endif
1385 return NULL;
1386 }
1387
1388 element++;
1389 pos_in_el=0;
1390 curr_len=SBALE_LEN(element);
1391
1392 if (curr_len<QETH_HEADER_SIZE) {
1393#ifdef QETH_DBF_LIKE_HELL
1394 sprintf(dbf_text,"gdnf%4x",card->irq0);
1395 QETH_DBF_TEXT6(0,trace,dbf_text);
1396#endif
1397 return NULL;
1398 }
1399 }
1400
1401 *hdr_ptr=SBALE_ADDR(element)+pos_in_el;
1402
1403 length=*(__u16*)((char*)(*hdr_ptr)+QETH_HEADER_LEN_POS);
1404
1405#ifdef QETH_DBF_LIKE_HELL
1406 sprintf(dbf_text,"gnHd%4x",card->irq0);
1407 QETH_DBF_TEXT6(0,trace,dbf_text);
1408 QETH_DBF_HEX6(0,trace,hdr_ptr,sizeof(void*));
1409#endif
1410
1411 pos_in_el+=QETH_HEADER_SIZE;
1412 if (curr_len<=pos_in_el) {
1413
1414 pos_in_el=0;
1415 element++;
1416 curr_len=SBALE_LEN(element);
1417 if (!curr_len) {
1418 PRINT_WARN("irq 0x%x: inb. buffer with more headers " \
1419 "than data areas (%i elements).\n",
1420 card->irq0,element);
1421 sprintf(dbf_text,"IEMH%4x",card->irq0);
1422 QETH_DBF_TEXT0(0,trace,dbf_text);
1423 sprintf(dbf_text,"%2x%2x%4x",element,*element_ptr,
1424 *pos_in_el_ptr);
1425 QETH_DBF_TEXT0(1,trace,dbf_text);
1426 QETH_DBF_HEX0(0,misc,buffer,QETH_DBF_MISC_LEN);
1427 QETH_DBF_HEX0(0,misc,buffer+QETH_DBF_MISC_LEN,
1428 QETH_DBF_MISC_LEN);
1429 return NULL;
1430 }
1431 }
1432
1433 data_ptr=SBALE_ADDR(element)+pos_in_el;
1434
1435 if (card->options.fake_ll==FAKE_LL) {
1436 skb=qeth_get_skb(length+QETH_FAKE_LL_LEN);
1437 if (!skb) goto nomem;
1438 skb_pull(skb,QETH_FAKE_LL_LEN);
1439 } else {
1440 skb=qeth_get_skb(length);
1441 if (!skb) goto nomem;
1442 }
1443
1444 if (card->easy_copy_cap)
1445 memcpy(skb_put(skb,length),data_ptr,length);
1446
1447#ifdef QETH_DBF_LIKE_HELL
1448 QETH_DBF_HEX6(0,trace,&data_ptr,sizeof(void*));
1449 QETH_DBF_HEX6(0,trace,&skb,sizeof(void*));
1450#endif
1451
1452 len_togo=length;
1453 while (1) {
1454 step=qeth_min(len_togo,curr_len-pos_in_el);
1455 if (!step) {
1456 PRINT_WARN("irq 0x%x: unexpected end of buffer, " \
1457 "length of element %i is 0. Discarding " \
1458 "packet.\n",card->irq0,element);
1459 sprintf(dbf_text,"IEUE%4x",card->irq0);
1460 QETH_DBF_TEXT0(0,trace,dbf_text);
1461 sprintf(dbf_text,"%2x%2x%4x",element,*element_ptr,
1462 *pos_in_el_ptr);
1463 QETH_DBF_TEXT0(0,trace,dbf_text);
1464 sprintf(dbf_text,"%4x%4x",len_togo,step);
1465 QETH_DBF_TEXT0(0,trace,dbf_text);
1466 sprintf(dbf_text,"%4x%4x",curr_len,pos_in_el);
1467 QETH_DBF_TEXT0(1,trace,dbf_text);
1468 QETH_DBF_HEX0(0,misc,buffer,QETH_DBF_MISC_LEN);
1469 QETH_DBF_HEX0(0,misc,buffer+QETH_DBF_MISC_LEN,
1470 QETH_DBF_MISC_LEN);
1471 dev_kfree_skb_irq(skb);
1472 return NULL;
1473 }
1474 if (!card->easy_copy_cap)
1475 memcpy(skb_put(skb,step),data_ptr,step);
1476 len_togo-=step;
1477 if (len_togo) {
1478 pos_in_el=0;
1479 element++;
1480 curr_len=SBALE_LEN(element);
1481 data_ptr=SBALE_ADDR(element);
1482 } else {
1483#ifdef QETH_INBOUND_PACKING_1_PACKET_PER_SBALE
1484 element++;
1485
1486 pos_in_el=0;
1487#else
1488 pos_in_el+=step;
1489#endif
1490 break;
1491 }
1492 }
1493
1494#ifdef QETH_DBF_LIKE_HELL
1495 sprintf(dbf_text,"%4x%4x",element,pos_in_el);
1496 QETH_DBF_TEXT6(0,trace,dbf_text);
1497#endif
1498
1499 *element_ptr=element;
1500 *pos_in_el_ptr=pos_in_el;
1501
1502 return skb;
1503
1504nomem:
1505 if (net_ratelimit()) {
1506 PRINT_WARN("no memory for packet from %s\n",card->dev_name);
1507 }
1508 sprintf(dbf_text,"NOMM%4x",card->irq0);
1509 QETH_DBF_TEXT0(0,trace,dbf_text);
1510 return NULL;
1511}
1512
1513static inline void qeth_transform_outbound_addrs(qeth_card_t *card,
1514 qdio_buffer_t *buffer)
1515{
1516 int i;
1517 void *ptr;
1518
1519 if (card->do_pfix) {
1520 for (i=0;i<QDIO_MAX_ELEMENTS_PER_BUFFER;i++) {
1521 ptr=buffer->element[i].addr;
1522 buffer->element[i].addr=(void *)pfix_get_addr(ptr);
1523 }
1524 }
1525}
1526static inline void qeth_get_linux_addrs_for_buffer(qeth_card_t *card,
1527 int buffer_no)
1528{
1529 int i;
1530 void *ptr;
1531
1532 if (card->do_pfix) {
1533 for (i=0;i<QDIO_MAX_ELEMENTS_PER_BUFFER;i++) {
1534 ptr=card->inbound_qdio_buffers[buffer_no].
1535 element[i].addr;
1536 card->inbound_qdio_buffers[buffer_no].element[i].addr=
1537 card->real_inb_buffer_addr[buffer_no][i]+
1538 ((unsigned long)ptr&(PAGE_SIZE-1));
1539 }
1540 }
1541}
1542
1543static inline void qeth_read_in_buffer(qeth_card_t *card,int buffer_no)
1544{
1545 struct sk_buff *skb;
1546 void *hdr_ptr;
1547 int element=0,pos_in_el=0;
1548 int version;
1549 qdio_buffer_t *buffer;
1550 unsigned short cast_type;
1551#ifdef QETH_VLAN
1552 __u16 *vlan_tag;
1553#endif
1554 int i;
1555 int max_elements;
1556 char dbf_text[15];
1557 struct net_device *dev;
1558
1559 dev=card->dev;
1560 max_elements=BUFFER_MAX_ELEMENTS;
1561
1562 buffer=&card->inbound_qdio_buffers[buffer_no];
1563
1564
1565 if (buffer->element[15].flags&0xff) {
1566 PRINT_WARN("on irq 0x%x: incoming SBALF 15 on buffer " \
1567 "0x%x are 0x%x\n",card->irq0,buffer_no,
1568 buffer->element[15].flags&0xff);
1569 sprintf(dbf_text,"SF##%2x%2x",buffer_no,
1570 buffer->element[15].flags&0xff);
1571 *((__u16*)(&dbf_text[2]))=(__u16)card->irq0;
1572 QETH_DBF_HEX1(1,trace,dbf_text,QETH_DBF_TRACE_LEN);
1573 }
1574
1575 for (i=0;i<max_elements-1;i++) {
1576 if (buffer->element[i].flags&SBAL_FLAGS_LAST_ENTRY) {
1577 buffer->element[i+1].length=0;
1578 break;
1579 }
1580 }
1581#ifdef QETH_PERFORMANCE_STATS
1582 card->perf_stats.bufs_rec++;
1583#endif
1584
1585#ifdef QETH_DBF_LIKE_HELL
1586 sprintf(dbf_text,"ribX%4x",card->irq0);
1587 dbf_text[3]=buffer_no;
1588 QETH_DBF_HEX6(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
1589#endif
1590
1591 while ((skb=qeth_get_next_skb(card,&element,&pos_in_el,
1592 &hdr_ptr,buffer))) {
1593
1594#ifdef QETH_PERFORMANCE_STATS
1595 card->perf_stats.skbs_rec++;
1596#endif
1597
1598 if (skb) {
1599 skb->dev=dev;
1600
1601#ifdef QETH_IPV6
1602 if ( (*(__u16 *)(hdr_ptr))&(QETH_HEADER_PASSTHRU) ) {
1603 skb->protocol=card->type_trans(skb,dev);
1604 } else
1605#endif
1606 {
1607 version=((*(__u16 *)(hdr_ptr))&
1608 (QETH_HEADER_IPV6))?6:4;
1609 skb->protocol=htons((version==4)?ETH_P_IP:
1610 (version==6)?ETH_P_IPV6:
1611 ETH_P_ALL);
1612 cast_type=(*(__u16 *)(hdr_ptr))&
1613 (QETH_CAST_FLAGS);
1614 if (cast_type==QETH_CAST_UNICAST) {
1615 skb->pkt_type=PACKET_HOST;
1616 } else if (cast_type==QETH_CAST_MULTICAST) {
1617 skb->pkt_type=PACKET_MULTICAST;
1618 } else if (cast_type==QETH_CAST_BROADCAST) {
1619 skb->pkt_type=PACKET_BROADCAST;
1620 } else if ( (cast_type==QETH_CAST_ANYCAST) ||
1621 (cast_type==QETH_CAST_NOCAST) ) {
1622 sprintf(dbf_text,"ribf%4x",card->irq0);
1623 QETH_DBF_TEXT2(0,trace,dbf_text);
1624 sprintf(dbf_text,"castan%2x",cast_type);
1625 QETH_DBF_TEXT2(1,trace,dbf_text);
1626 skb->pkt_type=PACKET_HOST;
1627 } else {
1628 PRINT_WARN("adapter is using an " \
1629 "unknown casting value " \
1630 "of 0x%x. Using " \
1631 "unicasting instead.\n",
1632 cast_type);
1633 skb->pkt_type=PACKET_HOST;
1634 sprintf(dbf_text,"ribf%4x",card->irq0);
1635 QETH_DBF_TEXT2(0,trace,dbf_text);
1636 sprintf(dbf_text,"castun%2x",cast_type);
1637 QETH_DBF_TEXT2(1,trace,dbf_text);
1638 }
1639
1640 if (card->options.fake_ll==FAKE_LL) {
1641 skb->mac.raw=skb->data-QETH_FAKE_LL_LEN;
1642 if (skb->pkt_type==PACKET_MULTICAST) {
1643 switch (skb->protocol) {
1644#ifdef QETH_IPV6
1645 case __constant_htons(ETH_P_IPV6):
1646 ndisc_mc_map((struct in6_addr *)
1647 skb->data+QETH_FAKE_LL_V6_ADDR_POS,
1648 skb->mac.raw+
1649 QETH_FAKE_LL_DEST_MAC_POS,
1650 card->dev,0);
1651 break;
1652#endif
1653 case __constant_htons(ETH_P_IP):
1654 qeth_get_mac_for_ipm(*(__u32*)
1655 skb->data+QETH_FAKE_LL_V4_ADDR_POS,
1656 skb->mac.raw+
1657 QETH_FAKE_LL_DEST_MAC_POS,
1658 card->dev);
1659 break;
1660 default:
1661 memcpy(skb->mac.raw+
1662 QETH_FAKE_LL_DEST_MAC_POS,
1663 card->dev->dev_addr,
1664 QETH_FAKE_LL_ADDR_LEN);
1665 }
1666 } else if (skb->pkt_type==PACKET_BROADCAST) {
1667 memset(skb->mac.raw+
1668 QETH_FAKE_LL_DEST_MAC_POS,0xff,
1669 QETH_FAKE_LL_ADDR_LEN);
1670 } else {
1671 memcpy(skb->mac.raw+
1672 QETH_FAKE_LL_DEST_MAC_POS,
1673 card->dev->dev_addr,
1674 QETH_FAKE_LL_ADDR_LEN);
1675 }
1676 if (*(__u8*)(hdr_ptr+11)&
1677 QETH_EXT_HEADER_SRC_MAC_ADDRESS) {
1678 memcpy(skb->mac.raw+
1679 QETH_FAKE_LL_SRC_MAC_POS,
1680 hdr_ptr+QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR,
1681 QETH_FAKE_LL_ADDR_LEN);
1682 } else {
1683
1684 memset(skb->mac.raw+
1685 QETH_FAKE_LL_SRC_MAC_POS,0,
1686 QETH_FAKE_LL_ADDR_LEN);
1687 }
1688 memcpy(skb->mac.raw+
1689 QETH_FAKE_LL_PROT_POS,
1690 &skb->protocol,
1691 QETH_FAKE_LL_PROT_LEN);
1692 } else {
1693 skb->mac.raw=skb->data;
1694 }
1695
1696 if (card->options.checksum_type==HW_CHECKSUMMING) {
1697
1698
1699
1700
1701
1702
1703
1704 if ( (*(__u8*)(hdr_ptr+11)&
1705 (QETH_EXT_HEADER_CSUM_HDR_REQ|
1706 QETH_EXT_HEADER_CSUM_TRANSP_REQ)) ==
1707 (QETH_EXT_HEADER_CSUM_HDR_REQ|
1708 QETH_EXT_HEADER_CSUM_TRANSP_REQ) ) {
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730 skb->ip_summed=CHECKSUM_UNNECESSARY;
1731 } else {
1732
1733 skb->ip_summed=CHECKSUM_NONE;
1734 }
1735 } else {
1736 skb->ip_summed=card->options.checksum_type;
1737 }
1738
1739#ifdef QETH_VLAN
1740 if (*(__u8*)(hdr_ptr+11)&
1741 QETH_EXT_HEADER_VLAN_FRAME) {
1742 vlan_tag=(__u16 *)skb_push(skb,
1743 VLAN_HLEN);
1744
1745
1746
1747
1748
1749
1750
1751 *vlan_tag = *(__u16*)(hdr_ptr+12);
1752 *(vlan_tag+1) = skb->protocol;
1753
1754
1755
1756 skb->protocol=
1757 __constant_htons(ETH_P_8021Q);
1758 }
1759#endif
1760 }
1761
1762#ifdef QETH_PERFORMANCE_STATS
1763 card->perf_stats.inbound_time+=
1764 NOW-card->perf_stats.inbound_start_time;
1765 card->perf_stats.inbound_cnt++;
1766#endif
1767
1768#ifdef QETH_DBF_LIKE_HELL
1769 sprintf(dbf_text,"rxpk%4x",card->irq0);
1770 QETH_DBF_TEXT6(0,trace,dbf_text);
1771#endif
1772
1773 netif_rx(skb);
1774
1775 card->stats->rx_packets++;
1776 card->stats->rx_bytes+=skb->len;
1777 } else {
1778 PRINT_WARN("%s: dropped packet, no buffers " \
1779 "available.\n",card->dev_name);
1780 sprintf(dbf_text,"DROP%4x",card->irq0);
1781 QETH_DBF_TEXT2(1,trace,dbf_text);
1782 card->stats->rx_dropped++;
1783 }
1784 }
1785 atomic_set(&card->inbound_buffer_refcnt[buffer_no],0);
1786 qeth_put_buffer_pool_entry(card,card->inbound_buffer_entry_no[
1787 buffer_no]);
1788}
1789
1790static inline void qeth_fill_header(qeth_hdr_t *hdr,struct sk_buff *skb,
1791 int version,int multicast)
1792{
1793#ifdef QETH_DBF_LIKE_HELL
1794 char dbf_text[15];
1795#endif
1796#ifdef QETH_VLAN
1797 qeth_card_t *card;
1798#endif
1799
1800 hdr->id=1;
1801 hdr->ext_flags=0;
1802
1803#ifdef QETH_VLAN
1804
1805
1806
1807 card = (qeth_card_t *)skb->dev->priv;
1808 if ((card->vlangrp != NULL) &&
1809 vlan_tx_tag_present(skb))
1810 {
1811 if (version == 4) {
1812 hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME;
1813 } else {
1814 hdr->ext_flags = QETH_EXT_HEADER_INCLUDE_VLAN_TAG;
1815 }
1816 hdr->vlan_id = vlan_tx_tag_get(skb);
1817 }
1818#endif
1819
1820 hdr->length=skb->len-QETH_HEADER_SIZE;
1821
1822
1823
1824
1825 if (version==4) {
1826 if (multicast==RTN_MULTICAST) {
1827 hdr->flags=QETH_CAST_MULTICAST;
1828 } else if (multicast==RTN_BROADCAST) {
1829 hdr->flags=QETH_CAST_BROADCAST;
1830 } else {
1831 hdr->flags=QETH_CAST_UNICAST;
1832 }
1833 *((__u32*)(&hdr->dest_addr[0]))=0;
1834 *((__u32*)(&hdr->dest_addr[4]))=0;
1835 *((__u32*)(&hdr->dest_addr[8]))=0;
1836 if ((skb->dst) && (skb->dst->neighbour)) {
1837 *((__u32*)(&hdr->dest_addr[12]))=
1838 *((__u32*)skb->dst->neighbour->primary_key);
1839 } else {
1840
1841
1842 *((__u32*)(&hdr->dest_addr[12]))=
1843 skb->nh.iph->daddr;
1844 }
1845 } else if (version==6) {
1846 if (multicast==RTN_MULTICAST) {
1847 hdr->flags=QETH_CAST_MULTICAST|
1848 QETH_HEADER_PASSTHRU|
1849 QETH_HEADER_IPV6;
1850 } else if (multicast==RTN_ANYCAST) {
1851 hdr->flags=QETH_CAST_ANYCAST|
1852 QETH_HEADER_PASSTHRU|
1853 QETH_HEADER_IPV6;
1854 } else if (multicast==RTN_BROADCAST) {
1855 hdr->flags=QETH_CAST_BROADCAST|
1856 QETH_HEADER_PASSTHRU|
1857 QETH_HEADER_IPV6;
1858 } else {
1859 hdr->flags=QETH_CAST_UNICAST|
1860 QETH_HEADER_PASSTHRU|
1861 QETH_HEADER_IPV6;
1862 }
1863
1864 if ((skb->dst) && (skb->dst->neighbour)) {
1865 memcpy(hdr->dest_addr,
1866 skb->dst->neighbour->primary_key,16);
1867 } else {
1868
1869
1870 memcpy(hdr->dest_addr,
1871 &skb->nh.ipv6h->daddr,16);
1872 }
1873 } else {
1874 if (!memcmp(skb->data+QETH_HEADER_SIZE,
1875 skb->dev->broadcast,6)) {
1876 hdr->flags=QETH_CAST_BROADCAST|QETH_HEADER_PASSTHRU;
1877 } else {
1878 if (multicast==RTN_MULTICAST) {
1879 hdr->flags=QETH_CAST_MULTICAST|
1880 QETH_HEADER_PASSTHRU;
1881 } else {
1882 hdr->flags=QETH_CAST_UNICAST|
1883 QETH_HEADER_PASSTHRU;
1884 }
1885 }
1886 }
1887#ifdef QETH_DBF_LIKE_HELL
1888 sprintf(dbf_text,"filhdr%2x",version);
1889 QETH_DBF_TEXT6(0,trace,dbf_text);
1890 sprintf(dbf_text,"%2x",multicast);
1891 QETH_DBF_TEXT6(0,trace,dbf_text);
1892 QETH_DBF_HEX6(0,trace,&skb,sizeof(void*));
1893 QETH_DBF_HEX6(0,trace,&skb->data,sizeof(void*));
1894 QETH_DBF_HEX6(0,misc,hdr,__max(QETH_HEADER_SIZE,QETH_DBF_MISC_LEN));
1895 QETH_DBF_HEX6(0,data,skb->data,
1896 __max(QETH_DBF_DATA_LEN,QETH_DBF_DATA_LEN));
1897#endif
1898}
1899
1900static inline int qeth_fill_buffer(qdio_buffer_t *buffer,char *dataptr,
1901 int length,int element)
1902{
1903 int length_here;
1904 int first_lap=1;
1905#ifdef QETH_DBF_LIKE_HELL
1906 char dbf_text[15];
1907#endif
1908 int first_element=element;
1909
1910 while (length>0) {
1911
1912 length_here=PAGE_SIZE-((unsigned long)dataptr&(PAGE_SIZE-1));
1913 if (length<length_here) length_here=length;
1914
1915 buffer->element[element].addr=dataptr;
1916 buffer->element[element].length=length_here;
1917 length-=length_here;
1918 if (!length) {
1919 if (first_lap) {
1920 buffer->element[element].flags=0;
1921 } else {
1922 buffer->element[element].flags=
1923 SBAL_FLAGS_LAST_FRAG;
1924 }
1925 } else {
1926 if (first_lap) {
1927 buffer->element[element].flags=
1928 SBAL_FLAGS_FIRST_FRAG;
1929 } else {
1930 buffer->element[element].flags=
1931 SBAL_FLAGS_MIDDLE_FRAG;
1932 }
1933 }
1934 dataptr=dataptr+length_here;
1935 element++;
1936 if (element>QDIO_MAX_ELEMENTS_PER_BUFFER) {
1937 PRINT_ERR("qeth_fill_buffer: IP packet too big!\n");
1938 QETH_DBF_TEXT1(0,trace,"IPpktobg");
1939 QETH_DBF_HEX1(1,trace,&dataptr,sizeof(void*));
1940 buffer->element[first_element].length=0;
1941 break;
1942 }
1943 first_lap=0;
1944 }
1945#ifdef QETH_DBF_LIKE_HELL
1946 sprintf(dbf_text,"filbuf%2x",element);
1947 QETH_DBF_TEXT6(0,trace,dbf_text);
1948 QETH_DBF_HEX3(0,misc,buffer,QETH_DBF_MISC_LEN);
1949 QETH_DBF_HEX3(0,misc,buffer+QETH_DBF_MISC_LEN,QETH_DBF_MISC_LEN);
1950#endif
1951
1952 return element;
1953}
1954
1955static inline void qeth_flush_packed_packets(qeth_card_t *card,int queue,
1956 int under_int)
1957{
1958 qdio_buffer_t *buffer;
1959 int result;
1960 int position;
1961 int position_for_do_qdio;
1962 char dbf_text[15];
1963 int last_pci;
1964
1965 position=card->outbound_first_free_buffer[queue];
1966
1967
1968 if (!card->outbound_ringbuffer[queue]->ringbuf_element[position].
1969 next_element_to_fill)
1970 return;
1971
1972 buffer=&card->outbound_ringbuffer[queue]->buffer[position];
1973 buffer->element[card->outbound_ringbuffer[queue]->
1974 ringbuf_element[position].
1975 next_element_to_fill-1].flags|=SBAL_FLAGS_LAST_ENTRY;
1976
1977 card->dev->trans_start=jiffies;
1978
1979#ifdef QETH_PERFORMANCE_STATS
1980 if (card->outbound_buffer_send_state[queue][position]==
1981 SEND_STATE_DONT_PACK) {
1982 card->perf_stats.bufs_sent_dont_pack++;
1983 } else if (card->outbound_buffer_send_state[queue][position]==
1984 SEND_STATE_PACK) {
1985 card->perf_stats.bufs_sent_pack++;
1986 }
1987 card->perf_stats.bufs_sent++;
1988#endif
1989
1990 position_for_do_qdio=position;
1991
1992 position=(position+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
1993 card->outbound_first_free_buffer[queue]=position;
1994
1995 card->outbound_bytes_in_buffer[queue]=0;
1996
1997 card->outbound_ringbuffer[queue]->ringbuf_element[position].
1998 next_element_to_fill=0;
1999
2000 atomic_inc(&card->outbound_used_buffers[queue]);
2001
2002#ifdef QETH_DBF_LIKE_HELL
2003 sprintf(dbf_text,"flsp%4x",card->irq0);
2004 QETH_DBF_TEXT5(0,trace,dbf_text);
2005 sprintf(dbf_text,"%4x%2x%2x",position_for_do_qdio,under_int,queue);
2006 QETH_DBF_TEXT5(0,trace,dbf_text);
2007 QETH_DBF_HEX5(0,misc,buffer,QETH_DBF_MISC_LEN);
2008 QETH_DBF_HEX5(0,misc,buffer+QETH_DBF_MISC_LEN,QETH_DBF_MISC_LEN);
2009#endif
2010
2011
2012
2013 switch (card->send_state[queue]) {
2014 case SEND_STATE_DONT_PACK:
2015
2016
2017
2018 if (atomic_read(&card->outbound_used_buffers[queue])
2019 <HIGH_WATERMARK_PACK-WATERMARK_FUZZ) break;
2020
2021 last_pci=atomic_read(&card->last_pci_pos[queue]);
2022
2023 if (position_for_do_qdio<last_pci)
2024 last_pci-=QDIO_MAX_BUFFERS_PER_Q;
2025
2026
2027
2028
2029 if (position_for_do_qdio-last_pci<
2030 HIGH_WATERMARK_PACK-WATERMARK_FUZZ) break;
2031
2032
2033 card->outbound_ringbuffer[queue]->
2034 buffer[position_for_do_qdio].element[0].flags|=0x40;
2035 atomic_set(&card->last_pci_pos[queue],position_for_do_qdio);
2036 break;
2037 case SEND_STATE_PACK:
2038 last_pci=atomic_read(&card->last_pci_pos[queue]);
2039 if (position_for_do_qdio<last_pci)
2040 last_pci-=QDIO_MAX_BUFFERS_PER_Q;
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057 if (position_for_do_qdio-
2058 atomic_read(&card->outbound_used_buffers[queue])>=
2059 last_pci) {
2060
2061 card->outbound_ringbuffer[queue]->
2062 buffer[position_for_do_qdio].
2063 element[0].flags|=0x40;
2064 atomic_set(&card->last_pci_pos[queue],
2065 position_for_do_qdio);
2066 }
2067 }
2068
2069 qeth_transform_outbound_addrs(card,
2070 &card->outbound_ringbuffer[queue]->
2071 buffer[position_for_do_qdio]);
2072
2073
2074 result=do_QDIO(card->irq2,QDIO_FLAG_SYNC_OUTPUT|under_int,queue,
2075 position_for_do_qdio,1,
2076 NULL);
2077
2078 if (result) {
2079 PRINT_WARN("Outbound do_QDIO returned %i " \
2080 "(irq 0x%x)\n",result,card->irq2);
2081 sprintf(dbf_text,"FLSP%4x",card->irq0);
2082 QETH_DBF_TEXT5(0,trace,dbf_text);
2083 sprintf(dbf_text,"odoQ%4x",result);
2084 QETH_DBF_TEXT5(0,trace,dbf_text);
2085 sprintf(dbf_text,"%4x%2x%2x",position_for_do_qdio,
2086 under_int,queue);
2087 QETH_DBF_TEXT5(0,trace,dbf_text);
2088 QETH_DBF_HEX5(0,misc,buffer,QETH_DBF_MISC_LEN);
2089 QETH_DBF_HEX5(0,misc,buffer+QETH_DBF_MISC_LEN,
2090 QETH_DBF_MISC_LEN);
2091 }
2092}
2093
2094#define ERROR_NONE 0
2095#define ERROR_RETRY 1
2096#define ERROR_LINK_FAILURE 2
2097#define ERROR_KICK_THAT_PUPPY 3
2098static inline int qeth_determine_send_error(int cc,int qdio_error,int sbalf15)
2099{
2100 char dbf_text[15];
2101
2102 switch (cc&3) {
2103 case 0:
2104 if (qdio_error)
2105 return ERROR_LINK_FAILURE;
2106 return ERROR_NONE;
2107 case 2:
2108 if (cc&QDIO_SIGA_ERROR_B_BIT_SET) {
2109 QETH_DBF_TEXT3(0,trace,"sigacc2b");
2110 return ERROR_KICK_THAT_PUPPY;
2111 }
2112 if (qeth_sbalf15_in_retrieable_range(sbalf15))
2113 return ERROR_RETRY;
2114 return ERROR_LINK_FAILURE;
2115
2116 case 1:
2117 PRINT_WARN("siga returned cc 1! cc=0x%x, " \
2118 "qdio_error=0x%x, sbalf15=0x%x\n",
2119 cc,qdio_error,sbalf15);
2120
2121 QETH_DBF_TEXT3(0,trace,"siga-cc1");
2122 QETH_DBF_TEXT2(0,qerr,"siga-cc1");
2123 sprintf(dbf_text,"%1x%2x%2x",cc,qdio_error,sbalf15);
2124 QETH_DBF_TEXT3(0,trace,dbf_text);
2125 QETH_DBF_TEXT2(0,qerr,dbf_text);
2126 return ERROR_LINK_FAILURE;
2127 case 3:
2128 QETH_DBF_TEXT3(0,trace,"siga-cc3");
2129 return ERROR_KICK_THAT_PUPPY;
2130 }
2131 return ERROR_LINK_FAILURE;
2132}
2133
2134static inline void qeth_free_buffer(qeth_card_t *card,int queue,int bufno,
2135 int qdio_error,int siga_error)
2136{
2137 struct sk_buff *skb;
2138 int error;
2139 int retries;
2140 int sbalf15;
2141 char dbf_text[15];
2142 qdio_buffer_t *buffer;
2143
2144 switch (card->outbound_buffer_send_state[queue][bufno]) {
2145 case SEND_STATE_DONT_PACK:
2146 case SEND_STATE_PACK:
2147#ifdef QETH_DBF_LIKE_HELL
2148 sprintf(dbf_text,"frbf%4x",card->irq0);
2149 QETH_DBF_TEXT5(0,trace,dbf_text);
2150 sprintf(dbf_text,"%2x%2x%4x",queue,bufno,
2151 card->outbound_buffer_send_state[queue][bufno]);
2152 QETH_DBF_TEXT5(0,trace,dbf_text);
2153#endif
2154
2155 buffer=&card->outbound_ringbuffer[queue]->buffer[bufno];
2156 sbalf15=buffer->element[15].flags&0xff;
2157 error=qeth_determine_send_error(siga_error,qdio_error,sbalf15);
2158 if (error==ERROR_KICK_THAT_PUPPY) {
2159 sprintf(dbf_text,"KP%4x%2x",card->irq0,queue);
2160 QETH_DBF_TEXT2(0,trace,dbf_text);
2161 QETH_DBF_TEXT2(0,qerr,dbf_text);
2162 QETH_DBF_TEXT2(1,setup,dbf_text);
2163 sprintf(dbf_text,"%2x%2x%2x%2x",bufno,
2164 siga_error,qdio_error,sbalf15);
2165 QETH_DBF_TEXT2(1,trace,dbf_text);
2166 QETH_DBF_TEXT2(1,qerr,dbf_text);
2167 PRINT_ERR("Outbound queue x%x on irq x%x (%s); " \
2168 "errs: siga: x%x, qdio: x%x, flags15: " \
2169 "x%x. The device will be taken down.\n",
2170 queue,card->irq0,card->dev_name,
2171 siga_error,qdio_error,sbalf15);
2172 netif_stop_queue(card->dev);
2173 qeth_set_dev_flag_norunning(card);
2174 atomic_set(&card->problem,PROBLEM_BAD_SIGA_RESULT);
2175 qeth_schedule_recovery(card);
2176 } else if (error==ERROR_RETRY) {
2177
2178 retries=card->send_retries[queue][bufno];
2179
2180 sprintf(dbf_text,"Rt%4x%2x",card->irq0,queue);
2181 QETH_DBF_TEXT4(0,trace,dbf_text);
2182 sprintf(dbf_text,"b%2x:%2x%2x",bufno,
2183 sbalf15,retries);
2184 QETH_DBF_TEXT4(0,trace,dbf_text);
2185
2186 if (++retries>SEND_RETRIES_ALLOWED) {
2187 error=ERROR_LINK_FAILURE;
2188 QETH_DBF_TEXT4(1,trace,"ndegelnd");
2189 }
2190
2191 } else if (error==ERROR_LINK_FAILURE) {
2192
2193
2194 sprintf(dbf_text,"Fail%4x",card->irq0);
2195 QETH_DBF_TEXT3(1,trace,dbf_text);
2196 QETH_DBF_HEX3(0,misc,buffer,QETH_DBF_MISC_LEN);
2197 QETH_DBF_HEX3(0,misc,buffer+QETH_DBF_MISC_LEN,
2198 QETH_DBF_MISC_LEN);
2199 }
2200
2201 while ((skb=skb_dequeue(&card->outbound_ringbuffer[queue]->
2202 ringbuf_element[bufno].skb_list))) {
2203 switch (error) {
2204 case ERROR_NONE:
2205 atomic_dec(&skb->users);
2206 dev_kfree_skb_irq(skb);
2207 break;
2208 case ERROR_RETRY:
2209 QETH_DBF_TEXT3(0,qerr,"RETRY!!!");
2210 QETH_DBF_TEXT4(0,trace,"RETRY!!!");
2211
2212 atomic_dec(&skb->users);
2213 dev_kfree_skb_irq(skb);
2214 break;
2215 case ERROR_LINK_FAILURE:
2216 case ERROR_KICK_THAT_PUPPY:
2217 QETH_DBF_TEXT4(0,trace,"endeglnd");
2218 card->stats->tx_dropped++;
2219 card->stats->tx_errors++;
2220 atomic_dec(&skb->users);
2221 dev_kfree_skb_irq(skb);
2222 break;
2223 }
2224 }
2225 break;
2226 default:
2227 PRINT_WARN("oops... wrong send_state on %s. " \
2228 "shouldn't happen " \
2229 "(line %i). q=%i, bufno=x%x, state=%i\n",
2230 card->dev_name,__LINE__,queue,bufno,
2231 card->outbound_buffer_send_state[queue][bufno]);
2232 sprintf(dbf_text,"UPSf%4x",card->irq0);
2233 QETH_DBF_TEXT0(1,trace,dbf_text);
2234 QETH_DBF_TEXT0(1,qerr,dbf_text);
2235 sprintf(dbf_text,"%2x%2x%4x",queue,bufno,
2236 card->outbound_buffer_send_state[queue][bufno]);
2237 QETH_DBF_TEXT0(1,trace,dbf_text);
2238 QETH_DBF_TEXT0(1,qerr,dbf_text);
2239 }
2240 card->outbound_buffer_send_state[queue][bufno]=SEND_STATE_INACTIVE;
2241 card->send_retries[queue][bufno]=0;
2242}
2243
2244static inline void qeth_free_all_skbs(qeth_card_t *card)
2245{
2246 int q,b;
2247
2248 for (q=0;q<card->no_queues;q++)
2249 for (b=0;b<QDIO_MAX_BUFFERS_PER_Q;b++)
2250 if (card->outbound_buffer_send_state[q][b]!=
2251 SEND_STATE_INACTIVE)
2252 qeth_free_buffer(card,q,b,0,0);
2253}
2254
2255static inline void qeth_flush_buffer(qeth_card_t *card,int queue,
2256 int under_int)
2257{
2258#ifdef QETH_DBF_LIKE_HELL
2259 char dbf_text[15];
2260 sprintf(dbf_text,"flsb%4x",card->irq0);
2261 QETH_DBF_TEXT5(0,trace,dbf_text);
2262 sprintf(dbf_text,"%2x%2x%2x",queue,under_int,
2263 card->outbound_buffer_send_state[queue][
2264 card->outbound_first_free_buffer[queue] ]);
2265 QETH_DBF_TEXT5(0,trace,dbf_text);
2266#endif
2267
2268 switch (card->outbound_buffer_send_state[queue][
2269 card->outbound_first_free_buffer[queue] ]) {
2270 case SEND_STATE_DONT_PACK: break;
2271 case SEND_STATE_PACK:
2272 qeth_flush_packed_packets(card,queue,under_int);
2273 break;
2274 default:break;
2275 }
2276}
2277#ifdef QETH_VLAN
2278
2279static inline void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb)
2280{
2281
2282
2283
2284
2285
2286#define TMP_CPYSIZE 4
2287 __u16 *tag;
2288 tag = (__u16*)skb_push(__skb, VLAN_HLEN);
2289 memcpy(__skb->data,
2290 __skb->data+TMP_CPYSIZE,TMP_CPYSIZE);
2291 memcpy(__skb->data+TMP_CPYSIZE,
2292 __skb->data+(2*TMP_CPYSIZE),TMP_CPYSIZE);
2293 memcpy(__skb->data+(2*TMP_CPYSIZE),
2294 __skb->data+(3*TMP_CPYSIZE),TMP_CPYSIZE);
2295 tag = (__u16*)(__skb->data+(3*TMP_CPYSIZE));
2296
2297
2298
2299
2300
2301 *tag = __constant_htons(ETH_P_8021Q);
2302 *(tag+1) = vlan_tx_tag_get(__skb);
2303 *(tag+1)=htons(*(tag+1));
2304#undef TMP_CPYSIZE
2305}
2306#endif
2307
2308
2309
2310static inline void qeth_send_packet_fast(qeth_card_t *card,struct sk_buff *skb,
2311 struct net_device *dev,
2312 int queue,int version,int multicast)
2313{
2314 qeth_ringbuffer_element_t *mybuffer;
2315 int position;
2316 qeth_hdr_t *hdr;
2317 char *dataptr;
2318 char dbf_text[15];
2319 struct sk_buff *nskb;
2320
2321 position=card->outbound_first_free_buffer[queue];
2322
2323 card->outbound_buffer_send_state[queue][position]=SEND_STATE_DONT_PACK;
2324
2325 mybuffer=&card->outbound_ringbuffer[queue]->ringbuf_element[position];
2326 if (skb_headroom(skb)<QETH_HEADER_SIZE) {
2327 if ((version)&&(!card->realloc_message)) {
2328 card->realloc_message=1;
2329 PRINT_WARN("%s: not enough headroom in skb. " \
2330 "Increasing the " \
2331 "add_hhlen parameter by %i may help.\n",
2332 card->dev_name,
2333 QETH_HEADER_SIZE-skb_headroom(skb));
2334 }
2335 PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n",
2336 card->dev_name,QETH_HEADER_SIZE-skb_headroom(skb));
2337 sprintf(dbf_text,"NHRf%4x",card->irq0);
2338 QETH_DBF_TEXT3(0,trace,dbf_text);
2339 sprintf(dbf_text,"%2x%2x%2x%2x",skb_headroom(skb),
2340 version,multicast,queue);
2341 QETH_DBF_TEXT3(0,trace,dbf_text);
2342 QETH_DBF_HEX3(0,trace,&skb->head,sizeof(void*));
2343 QETH_DBF_HEX3(0,trace,&skb->data,sizeof(void*));
2344 nskb=skb_realloc_headroom(skb,QETH_HEADER_SIZE);
2345 if (!nskb) {
2346 PRINT_WARN("%s: could not realloc headroom\n",
2347 card->dev_name);
2348 sprintf(dbf_text,"CNRf%4x",card->irq0);
2349 QETH_DBF_TEXT2(0,trace,dbf_text);
2350 dev_kfree_skb_irq(skb);
2351 return;
2352 }
2353 dev_kfree_skb_irq(skb);
2354 skb=nskb;
2355 }
2356#ifdef QETH_VLAN
2357 if ( (card->vlangrp != NULL) &&
2358 vlan_tx_tag_present(skb) &&
2359 (version==6)) {
2360 qeth_insert_ipv6_vlan_tag(skb);
2361 }
2362#endif
2363 hdr=(qeth_hdr_t*)(skb_push(skb,QETH_HEADER_SIZE));
2364
2365
2366
2367 dataptr=(char*)hdr;
2368 if ( (((unsigned long)dataptr)&(~(PAGE_SIZE-1))) !=
2369 ( ((unsigned long)dataptr+QETH_HEADER_SIZE+QETH_IP_HEADER_SIZE)&
2370 (~(PAGE_SIZE-1)) ) ) {
2371 PRINT_ERR("%s: packet misaligned -- the first %i bytes " \
2372 "are not in the same page. Discarding packet!\n",
2373 card->dev_name,
2374 QETH_HEADER_SIZE+QETH_IP_HEADER_SIZE);
2375 PRINT_ERR("head=%p, data=%p\n",skb->head,skb->data);
2376 sprintf(dbf_text,"PMAf%4x",card->irq0);
2377 QETH_DBF_TEXT1(0,trace,dbf_text);
2378 sprintf(dbf_text,"%2x%2x%2x%2x",skb_headroom(skb),
2379 version,multicast,queue);
2380 QETH_DBF_TEXT1(0,trace,dbf_text);
2381 QETH_DBF_HEX1(0,trace,&skb->head,sizeof(void*));
2382 QETH_DBF_HEX1(1,trace,&skb->data,sizeof(void*));
2383 dev_kfree_skb_irq(skb);
2384 return;
2385 }
2386
2387 atomic_inc(&skb->users);
2388 skb_queue_tail(&mybuffer->skb_list,skb);
2389 qeth_fill_header(hdr,skb,version,multicast);
2390
2391
2392 card->outbound_ringbuffer[queue]->ringbuf_element[position].
2393 next_element_to_fill=
2394 qeth_fill_buffer(&card->outbound_ringbuffer[queue]->
2395 buffer[position],(char *)hdr,
2396 skb->len,0);
2397
2398#ifdef QETH_PERFORMANCE_STATS
2399 card->perf_stats.skbs_sent_dont_pack++;
2400#endif
2401
2402 qeth_flush_packed_packets(card,queue,0);
2403}
2404
2405
2406
2407static inline void qeth_send_packet_packed(qeth_card_t *card,
2408 struct sk_buff *skb,
2409 struct net_device *dev,
2410 int queue,int version,
2411 int multicast)
2412{
2413 qeth_ringbuffer_element_t *mybuffer;
2414 int elements_needed;
2415 int element_to_fill;
2416 int buffer_no;
2417 int length;
2418 char *dataptr;
2419 qeth_hdr_t *hdr;
2420 char dbf_text[15];
2421 struct sk_buff *nskb;
2422
2423
2424 if (skb_headroom(skb)<QETH_HEADER_SIZE) {
2425 if ((version)&&(!card->realloc_message)) {
2426 card->realloc_message=1;
2427 PRINT_WARN("%s: not enough headroom in skb. " \
2428 "Try increasing the " \
2429 "add_hhlen parameter by %i.\n",
2430 card->dev_name,
2431 QETH_HEADER_SIZE-skb_headroom(skb));
2432 }
2433 PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n",
2434 card->dev_name,QETH_HEADER_SIZE-skb_headroom(skb));
2435 sprintf(dbf_text,"NHRp%4x",card->irq0);
2436 QETH_DBF_TEXT3(0,trace,dbf_text);
2437 sprintf(dbf_text,"%2x%2x%2x%2x",skb_headroom(skb),
2438 version,multicast,queue);
2439 QETH_DBF_TEXT3(0,trace,dbf_text);
2440 QETH_DBF_HEX3(0,trace,&skb->head,sizeof(void*));
2441 QETH_DBF_HEX3(0,trace,&skb->data,sizeof(void*));
2442 nskb=skb_realloc_headroom(skb,QETH_HEADER_SIZE);
2443 if (!nskb) {
2444 PRINT_WARN("%s: could not realloc headroom\n",
2445 card->dev_name);
2446 sprintf(dbf_text,"CNRp%4x",card->irq0);
2447 QETH_DBF_TEXT2(0,trace,dbf_text);
2448 dev_kfree_skb_irq(skb);
2449 return;
2450 }
2451 dev_kfree_skb_irq(skb);
2452 skb=nskb;
2453 }
2454#ifdef QETH_VLAN
2455 if ( (card->vlangrp != NULL) &&
2456 vlan_tx_tag_present(skb) &&
2457 (version==6)) {
2458 qeth_insert_ipv6_vlan_tag(skb);
2459 }
2460
2461#endif
2462 hdr=(qeth_hdr_t*)(skb_push(skb,QETH_HEADER_SIZE));
2463
2464 length=skb->len;
2465
2466
2467
2468
2469 dataptr=(char*)hdr;
2470 if ( (((unsigned long)dataptr)&(~(PAGE_SIZE-1))) !=
2471 ( ((unsigned long)dataptr+QETH_HEADER_SIZE+QETH_IP_HEADER_SIZE)&
2472 (~(PAGE_SIZE-1)) ) ) {
2473 PRINT_ERR("%s: packet misaligned -- the first %i bytes " \
2474 "are not in the same page. Discarding packet!\n",
2475 card->dev_name,
2476 QETH_HEADER_SIZE+QETH_IP_HEADER_SIZE);
2477 sprintf(dbf_text,"PMAp%4x",card->irq0);
2478 QETH_DBF_TEXT1(0,trace,dbf_text);
2479 sprintf(dbf_text,"%2x%2x%2x%2x",skb_headroom(skb),
2480 version,multicast,queue);
2481 QETH_DBF_TEXT1(0,trace,dbf_text);
2482 QETH_DBF_HEX1(0,trace,&skb->head,sizeof(void*));
2483 QETH_DBF_HEX1(1,trace,&skb->data,sizeof(void*));
2484 dev_kfree_skb_irq(skb);
2485 return;
2486 }
2487
2488 buffer_no=card->outbound_first_free_buffer[queue];
2489
2490 element_to_fill=card->outbound_ringbuffer[queue]->
2491 ringbuf_element[buffer_no].
2492 next_element_to_fill;
2493
2494 elements_needed=1+( ( (((unsigned long)dataptr)&(PAGE_SIZE-1))+
2495 length ) >>PAGE_SHIFT);
2496 if ( (elements_needed>(QDIO_MAX_ELEMENTS_PER_BUFFER-element_to_fill)) ||
2497 ( (elements_needed==
2498 (QDIO_MAX_ELEMENTS_PER_BUFFER-element_to_fill)) &&
2499 ((element_to_fill>>PAGE_SHIFT)==
2500 card->outbound_bytes_in_buffer[queue]) ) ) {
2501 qeth_flush_packed_packets(card,queue,0);
2502 element_to_fill=0;
2503 card->outbound_bytes_in_buffer[queue]=0;
2504 buffer_no=(buffer_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
2505 }
2506
2507 if (!element_to_fill)
2508 card->outbound_buffer_send_state[queue][buffer_no]
2509 =SEND_STATE_PACK;
2510
2511#ifdef QETH_PERFORMANCE_STATS
2512 card->perf_stats.skbs_sent_pack++;
2513#endif
2514
2515 mybuffer=&card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no];
2516 atomic_inc(&skb->users);
2517 skb_queue_tail(&mybuffer->skb_list,skb);
2518 qeth_fill_header(hdr,skb,version,multicast);
2519 card->outbound_bytes_in_buffer[queue]+=length+QETH_HEADER_SIZE;
2520 card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no].
2521 next_element_to_fill=
2522 qeth_fill_buffer(&card->outbound_ringbuffer[queue]->
2523 buffer[buffer_no],
2524 dataptr,length,element_to_fill);
2525}
2526
2527static void qeth_alloc_spare_bufs(void)
2528{
2529 int i;
2530 int dont_alloc_more=0;
2531 char dbf_text[15];
2532
2533 sparebuffer_count=0;
2534 for (i=0;i<qeth_sparebufs;i++) {
2535 if (!dont_alloc_more) {
2536 sparebufs[i].buf=(char*)
2537 kmalloc(DEFAULT_BUFFER_SIZE,GFP_KERNEL);
2538 if (sparebufs[i].buf)
2539 sparebuffer_count++;
2540 else
2541 dont_alloc_more=1;
2542 }
2543 atomic_set(&sparebufs[i].status,(dont_alloc_more)?
2544 SPAREBUF_UNAVAIL:SPAREBUF_FREE);
2545 }
2546 sprintf(dbf_text,"alspb%3x",sparebuffer_count);
2547 QETH_DBF_TEXT2(0,trace,dbf_text);
2548
2549 PRINT_INFO("allocated %i spare buffers\n",sparebuffer_count);
2550}
2551
2552static void qeth_free_all_spare_bufs(void)
2553{
2554 int i;
2555
2556 QETH_DBF_TEXT2(0,trace,"frealspb");
2557
2558 for (i=0;i<qeth_sparebufs;i++)
2559 if (atomic_read(&sparebufs[i].status)!=SPAREBUF_UNAVAIL) {
2560 kfree(sparebufs[i].buf);
2561 atomic_set(&sparebufs[i].status,SPAREBUF_UNAVAIL);
2562 }
2563}
2564
2565static __inline__ int atomic_return_sub(int i, atomic_t *v)
2566{
2567 int old_val, new_val;
2568 __CS_LOOP(old_val, new_val, v, i, "sr");
2569 return old_val;
2570}
2571
2572static inline int qeth_do_send_packet(qeth_card_t *card,struct sk_buff *skb,
2573 struct net_device *dev)
2574{
2575 int queue,result=0;
2576 int multicast,version;
2577 char dbf_text[15];
2578 char dbf_text2[15]="stchupXX";
2579
2580 version=QETH_IP_VERSION(skb);
2581 multicast=qeth_is_multicast_skb_at_all(skb,version);
2582 queue=qeth_get_prioqueue(card,skb,multicast,version);
2583
2584#ifdef QETH_DBF_LIKE_HELL
2585 sprintf(dbf_text,"dsp:%4x",card->irq0);
2586 QETH_DBF_TEXT6(0,trace,dbf_text);
2587 sprintf(dbf_text,"%c %c%4x",(version==4)?'4':((version==6)?'6':'0'),
2588 (multicast)?'m':'_',queue);
2589 QETH_DBF_TEXT6(0,trace,dbf_text);
2590 sprintf(dbf_text,"%4x%4x",
2591 card->outbound_first_free_buffer[queue],
2592 atomic_read(&card->outbound_used_buffers[queue]));
2593 QETH_DBF_TEXT6(0,trace,dbf_text);
2594 if (qeth_sbal_packing_on_card(card->type)) {
2595 switch (card->send_state[queue]) {
2596 case SEND_STATE_DONT_PACK:
2597 QETH_DBF_TEXT6(0,trace,"usngfast");
2598 break;
2599 case SEND_STATE_PACK:
2600 QETH_DBF_TEXT6(0,trace,"usngpack");
2601 break;
2602 }
2603 } else {
2604 QETH_DBF_TEXT6(0,trace,"usngfast");
2605 }
2606#endif
2607
2608 if (atomic_read(&card->outbound_used_buffers[queue])
2609 >=QDIO_MAX_BUFFERS_PER_Q-1) {
2610 sprintf(dbf_text,"cdbs%4x",card->irq0);
2611 QETH_DBF_TEXT2(1,trace,dbf_text);
2612 netif_stop_queue(dev);
2613 return -EBUSY;
2614 }
2615
2616
2617
2618
2619 if (atomic_compare_and_swap(QETH_LOCK_UNLOCKED,QETH_LOCK_NORMAL,
2620 &card->outbound_ringbuffer_lock[queue])) {
2621 sprintf(dbf_text,"SPIN%4x",card->irq0);
2622 QETH_DBF_TEXT2(0,trace,dbf_text);
2623 while (atomic_compare_and_swap
2624 (QETH_LOCK_UNLOCKED,QETH_LOCK_NORMAL,
2625 &card->outbound_ringbuffer_lock[queue]))
2626 ;
2627 sprintf(dbf_text,"spin%4x",card->irq0);
2628 QETH_DBF_TEXT2(0,trace,dbf_text);
2629 }
2630
2631#ifdef QETH_PERFORMANCE_STATS
2632 card->perf_stats.skbs_sent++;
2633#endif
2634
2635 if (qeth_sbal_packing_on_card(card->type)) {
2636 switch (card->send_state[queue]) {
2637 case SEND_STATE_DONT_PACK:
2638 qeth_send_packet_fast(card,skb,dev,queue,
2639 version,multicast);
2640 if (atomic_read(&card->outbound_used_buffers[queue])
2641 >=HIGH_WATERMARK_PACK) {
2642 card->send_state[queue]=SEND_STATE_PACK;
2643 *((__u16*)(&dbf_text2[6]))=card->irq0;
2644 QETH_DBF_HEX3(0,trace,dbf_text2,
2645 QETH_DBF_TRACE_LEN);
2646#ifdef QETH_PERFORMANCE_STATS
2647 card->perf_stats.sc_dp_p++;
2648#endif
2649 }
2650 break;
2651 case SEND_STATE_PACK:
2652 qeth_send_packet_packed(card,skb,dev,queue,
2653 version,multicast);
2654 break;
2655 default:
2656 result=-EBUSY;
2657 sprintf(dbf_text,"UPSs%4x",card->irq0);
2658 QETH_DBF_TEXT0(1,trace,dbf_text);
2659 PRINT_ALL("oops... shouldn't happen (line %i:%i).\n",
2660 __LINE__,card->send_state[queue]);
2661 }
2662 } else {
2663 qeth_send_packet_fast(card,skb,dev,queue,
2664 version,multicast);
2665 }
2666
2667again:
2668
2669 if (atomic_dec_return(&card->outbound_ringbuffer_lock[queue])) {
2670 qeth_flush_buffer(card,queue,0);
2671 card->send_state[queue]=SEND_STATE_DONT_PACK;
2672 goto again;
2673 }
2674
2675#ifdef QETH_PERFORMANCE_STATS
2676 card->perf_stats.outbound_time+=
2677 NOW-card->perf_stats.outbound_start_time;
2678 card->perf_stats.outbound_cnt++;
2679#endif
2680
2681 card->stats->tx_packets++;
2682 card->stats->tx_bytes+=skb->len;
2683
2684 return result;
2685}
2686
2687static int qeth_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
2688{
2689 qeth_card_t *card;
2690 char dbf_text[15];
2691 int result;
2692 unsigned long stackptr;
2693
2694 card=(qeth_card_t*)(dev->priv);
2695
2696 if (skb==NULL)
2697 return 0;
2698
2699#ifdef CONFIG_ARCH_S390X
2700 asm volatile ("lgr %0,15" : "=d" (stackptr));
2701#else
2702 asm volatile ("lr %0,15" : "=d" (stackptr));
2703#endif
2704
2705
2706
2707 if ( (stackptr & STACK_PTR_MASK)<
2708 (sizeof(struct task_struct) + WORST_CASE_STACK_USAGE) ) {
2709 PRINT_ERR("delaying packet transmission " \
2710 "due to potential stack overflow\n");
2711 sprintf(dbf_text,"STOF%4x",card->irq0);
2712 QETH_DBF_TEXT1(1,trace,dbf_text);
2713 PRINT_ERR("Backtrace follows:\n");
2714 show_trace((unsigned long *)stackptr);
2715 return -EBUSY;
2716 }
2717
2718#ifdef QETH_DBF_LIKE_HELL
2719 QETH_DBF_HEX4(0,data,skb->data,__max(QETH_DBF_DATA_LEN,skb->len));
2720#endif
2721
2722 netif_stop_queue(dev);
2723
2724 if (!card) {
2725 QETH_DBF_TEXT2(0,trace,"XMNSNOCD");
2726 card->stats->tx_dropped++;
2727 card->stats->tx_errors++;
2728 dev_kfree_skb_irq(skb);
2729 return 0;
2730 }
2731
2732#ifdef QETH_PERFORMANCE_STATS
2733 card->perf_stats.outbound_start_time=NOW;
2734#endif
2735
2736 if (!atomic_read(&card->is_startlaned)) {
2737 card->stats->tx_carrier_errors++;
2738 sprintf(dbf_text,"XMNS%4x",card->irq0);
2739 QETH_DBF_TEXT2(0,trace,dbf_text);
2740 card->stats->tx_dropped++;
2741 card->stats->tx_errors++;
2742 dev_kfree_skb_irq(skb);
2743 return 0;
2744 }
2745
2746 if (dev->hard_header == qeth_fake_header) {
2747
2748
2749
2750
2751
2752
2753
2754
2755 if ((skb = qeth_pskb_unshare(skb, GFP_ATOMIC)) == NULL) {
2756 card->stats->tx_dropped++;
2757 dev_kfree_skb_irq(skb);
2758 return 0;
2759 }
2760 skb_pull(skb, QETH_FAKE_LL_LEN);
2761 }
2762
2763 result=qeth_do_send_packet(card,skb,dev);
2764
2765 if (!result)
2766 netif_wake_queue(card->dev);
2767
2768 return result;
2769}
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784int qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
2785 unsigned short type, void *daddr, void *saddr,
2786 unsigned len)
2787{
2788 unsigned char *hdr;
2789
2790 hdr = skb_push(skb, QETH_FAKE_LL_LEN);
2791 memcpy(hdr, "FAKELLFAKELL", ETH_ALEN*2);
2792 if (type != ETH_P_802_3)
2793 *(u16 *)(hdr + ETH_ALEN*2) = htons(type);
2794 else
2795 *(u16 *)(hdr + ETH_ALEN*2) = htons(len);
2796
2797
2798 return QETH_FAKE_LL_LEN;
2799}
2800
2801static struct net_device_stats* qeth_get_stats(struct net_device *dev)
2802{
2803 qeth_card_t *card;
2804 char dbf_text[15];
2805
2806 card=(qeth_card_t*)(dev->priv);
2807
2808 sprintf(dbf_text,"gtst%4x",card->irq0);
2809 QETH_DBF_TEXT3(0,trace,dbf_text);
2810
2811 return card->stats;
2812}
2813
2814static int qeth_change_mtu(struct net_device *dev,int new_mtu)
2815{
2816 qeth_card_t *card;
2817 char dbf_text[15];
2818
2819 card=(qeth_card_t*)(dev->priv);
2820
2821 sprintf(dbf_text,"mtu %4x",card->irq0);
2822 QETH_DBF_TEXT2(0,trace,dbf_text);
2823 sprintf(dbf_text,"%8x",new_mtu);
2824 QETH_DBF_TEXT2(0,trace,dbf_text);
2825
2826 if (new_mtu<64) return -EINVAL;
2827 if (new_mtu>65535) return -EINVAL;
2828 if ((!qeth_is_supported(IPA_IP_FRAGMENTATION)) &&
2829 (!qeth_mtu_is_valid(card,new_mtu)))
2830 return -EINVAL;
2831 dev->mtu=new_mtu;
2832 return 0;
2833}
2834
2835static void qeth_start_softsetup_thread(qeth_card_t *card)
2836{
2837 char dbf_text[15];
2838 if (!atomic_read(&card->shutdown_phase)) {
2839 sprintf(dbf_text,"stss%4x",card->irq0);
2840 QETH_DBF_TEXT2(0,trace,dbf_text);
2841 up(&card->softsetup_thread_sem);
2842 }
2843}
2844
2845static int qeth_sleepon(qeth_card_t *card,int timeout)
2846{
2847 unsigned long flags;
2848 unsigned long start;
2849 int retval;
2850 char dbf_text[15];
2851
2852 DECLARE_WAITQUEUE (current_wait_q,current);
2853
2854 sprintf(dbf_text,"slpn%4x",card->irq0);
2855 QETH_DBF_TEXT5(0,trace,dbf_text);
2856 sprintf(dbf_text,"%08x",timeout);
2857 QETH_DBF_TEXT5(0,trace,dbf_text);
2858
2859 add_wait_queue(&card->wait_q,¤t_wait_q);
2860 atomic_set(&card->wait_q_active,1);
2861 start=qeth_get_millis();
2862 for (;;) {
2863 set_task_state(current,TASK_INTERRUPTIBLE);
2864 if (atomic_read(&card->data_has_arrived)) {
2865 atomic_set(&card->data_has_arrived,0);
2866 retval=0;
2867 goto out;
2868 }
2869 if (qeth_get_millis()-start>timeout) {
2870 retval=-ETIME;
2871 goto out;
2872 }
2873 schedule_timeout(((start+timeout-qeth_get_millis())>>10)*HZ);
2874 }
2875 out:
2876 spin_lock_irqsave(&card->wait_q_lock,flags);
2877 atomic_set(&card->wait_q_active,0);
2878 spin_unlock_irqrestore(&card->wait_q_lock,flags);
2879
2880
2881 if (atomic_read(&card->data_has_arrived)) {
2882 atomic_set(&card->data_has_arrived,0);
2883 retval=0;
2884 }
2885
2886 set_task_state(current,TASK_RUNNING);
2887 remove_wait_queue(&card->wait_q,¤t_wait_q);
2888
2889 return retval;
2890}
2891
2892static void qeth_wakeup_ioctl(qeth_card_t *card) {
2893 char dbf_text[15];
2894
2895 sprintf(dbf_text,"wkup%4x",card->irq0);
2896 QETH_DBF_TEXT5(0,trace,dbf_text);
2897
2898 atomic_set(&card->ioctl_data_has_arrived,1);
2899 spin_lock(&card->ioctl_wait_q_lock);
2900 if (atomic_read(&card->ioctl_wait_q_active)) {
2901 wake_up(&card->ioctl_wait_q);
2902 }
2903 spin_unlock(&card->ioctl_wait_q_lock);
2904}
2905
2906static int qeth_sleepon_ioctl(qeth_card_t *card,int timeout)
2907{
2908 unsigned long flags;
2909 unsigned long start;
2910 int retval;
2911 char dbf_text[15];
2912
2913 DECLARE_WAITQUEUE (current_wait_q,current);
2914
2915 sprintf(dbf_text,"ioctlslpn%4x",card->irq0);
2916 QETH_DBF_TEXT5(0,trace,dbf_text);
2917 sprintf(dbf_text,"%08x",timeout);
2918 QETH_DBF_TEXT5(0,trace,dbf_text);
2919
2920 save_flags(flags);
2921 add_wait_queue(&card->ioctl_wait_q,¤t_wait_q);
2922 atomic_set(&card->ioctl_wait_q_active,1);
2923 start=qeth_get_millis();
2924 for (;;) {
2925 set_task_state(current,TASK_INTERRUPTIBLE);
2926 if (atomic_read(&card->ioctl_data_has_arrived)) {
2927 atomic_set(&card->ioctl_data_has_arrived,0);
2928 retval=0;
2929 goto out;
2930 }
2931 if (qeth_get_millis()-start>timeout) {
2932 retval=-ETIME;
2933 goto out;
2934 }
2935 schedule_timeout(((start+timeout-qeth_get_millis())>>10)*HZ);
2936 }
2937 out:
2938 spin_lock_irqsave(&card->ioctl_wait_q_lock,flags);
2939 atomic_set(&card->ioctl_wait_q_active,0);
2940 spin_unlock_irqrestore(&card->ioctl_wait_q_lock,flags);
2941
2942
2943 if (atomic_read(&card->ioctl_data_has_arrived)) {
2944 atomic_set(&card->ioctl_data_has_arrived,0);
2945 retval=0;
2946 }
2947
2948 set_task_state(current,TASK_RUNNING);
2949 remove_wait_queue(&card->ioctl_wait_q,¤t_wait_q);
2950
2951 return retval;
2952}
2953
2954static void qeth_snmp_notify(void)
2955{
2956
2957 struct list_head *l;
2958 struct qeth_notify_list *n_entry;
2959
2960 QETH_DBF_TEXT5(0,trace,"snmpnoti");
2961 spin_lock(¬ify_lock);
2962 list_for_each(l, ¬ify_list) {
2963 n_entry = list_entry(l, struct qeth_notify_list, list);
2964 send_sig(n_entry->signum, n_entry->task, 1);
2965 }
2966 spin_unlock(¬ify_lock);
2967}
2968
2969static char* qeth_send_control_data(qeth_card_t *card,unsigned char *buffer,
2970 int len,unsigned long intparam)
2971{
2972 unsigned long flags;
2973 int result,result2;
2974 char dbf_text[15];
2975 unsigned char *rec_buf;
2976 int setip=(intparam&IPA_SETIP_FLAG)?1:0;
2977
2978again:
2979 if (atomic_read(&card->shutdown_phase)==
2980 QETH_REMOVE_CARD_QUICK) return NULL;
2981 if (atomic_read(&card->escape_softsetup))
2982 return NULL;
2983
2984
2985 if (atomic_swap(&card->write_busy,1)) {
2986 qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME);
2987 sprintf(dbf_text,"LSCD%4x",card->irq0);
2988 QETH_DBF_TEXT2(0,trace,dbf_text);
2989 goto again;
2990 }
2991 memcpy(card->dma_stuff->sendbuf,card->send_buf,QETH_BUFSIZE);
2992
2993 memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(buffer),
2994 &card->seqno.trans_hdr,QETH_SEQ_NO_LENGTH);
2995 card->seqno.trans_hdr++;
2996
2997 memcpy(QETH_PDU_HEADER_SEQ_NO(buffer),
2998 &card->seqno.pdu_hdr,QETH_SEQ_NO_LENGTH);
2999 card->seqno.pdu_hdr++;
3000 memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(buffer),
3001 &card->seqno.pdu_hdr_ack,QETH_SEQ_NO_LENGTH);
3002
3003
3004 atomic_set(&card->data_has_arrived,0);
3005
3006 memcpy(&card->dma_stuff->write_ccw,WRITE_CCW,sizeof(ccw1_t));
3007 card->dma_stuff->write_ccw.count=len;
3008 card->dma_stuff->write_ccw.cda=
3009 QETH_GET_ADDR(card->dma_stuff->sendbuf);
3010
3011 sprintf(dbf_text,"scdw%4x",card->irq0);
3012 QETH_DBF_TEXT2(0,trace,dbf_text);
3013 sprintf(dbf_text,"%8x",len);
3014 QETH_DBF_TEXT4(0,trace,dbf_text);
3015 QETH_DBF_HEX4(0,trace,&intparam,QETH_DBF_TRACE_LEN);
3016 QETH_DBF_HEX2(0,control,buffer,QETH_DBF_CONTROL_LEN);
3017
3018 s390irq_spin_lock_irqsave(card->irq1,flags);
3019 result=do_IO(card->irq1,&card->dma_stuff->write_ccw,intparam,0,0);
3020 if (result) {
3021 qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
3022 result2=do_IO(card->irq1,&card->dma_stuff->write_ccw,
3023 intparam,0,0);
3024 if (result2!=-ENODEV)
3025 PRINT_WARN("qeth_send_control_data: do_IO " \
3026 "returned %i, next try returns %i\n",
3027 result,result2);
3028 result=result2;
3029 }
3030 s390irq_spin_unlock_irqrestore(card->irq1,flags);
3031
3032 if (result) {
3033 QETH_DBF_TEXT2(0,trace,"scd:doio");
3034 sprintf(dbf_text,"%4x",(__s16)result);
3035 QETH_DBF_TEXT2(0,trace,dbf_text);
3036
3037 atomic_set(&card->write_busy,0);
3038 return NULL;
3039 }
3040
3041 if (intparam==IPA_IOCTL_STATE) {
3042 if (qeth_sleepon_ioctl(card,QETH_IPA_TIMEOUT)) {
3043 QETH_DBF_TEXT2(0,trace,"scd:ioct");
3044
3045 atomic_set(&card->write_busy,0);
3046 return NULL;
3047 }
3048 rec_buf=card->dma_stuff->recbuf;
3049 sprintf(dbf_text,"scro%4x",card->irq0);
3050 } else {
3051 if (qeth_sleepon(card,(setip)?QETH_IPA_TIMEOUT:
3052 QETH_MPC_TIMEOUT)) {
3053 QETH_DBF_TEXT2(0,trace,"scd:time");
3054
3055 atomic_set(&card->write_busy,0);
3056 return NULL;
3057 }
3058 rec_buf=card->ipa_buf;
3059 sprintf(dbf_text,"scri%4x",card->irq0);
3060 }
3061 QETH_DBF_TEXT2(0,trace,dbf_text);
3062 QETH_DBF_HEX2(0,control,rec_buf,QETH_DBF_CONTROL_LEN);
3063
3064 memcpy(&card->seqno.pdu_hdr_ack,
3065 QETH_PDU_HEADER_SEQ_NO(rec_buf),
3066 QETH_SEQ_NO_LENGTH);
3067
3068 return rec_buf;
3069}
3070
3071static int qeth_send_ipa_cmd(qeth_card_t *card,ipa_cmd_t *cmd,int update_cmd,
3072 int ipatype)
3073{
3074 unsigned char *buffer;
3075 ipa_cmd_t *reply;
3076 int ipa_cmd;
3077 int result;
3078
3079
3080 if ( (cmd->prot_version==6) &&
3081 (!qeth_is_supported(IPA_IPv6)) ) return 0;
3082
3083 ipa_cmd=cmd->command;
3084
3085 memcpy(card->send_buf,IPA_PDU_HEADER,
3086 IPA_PDU_HEADER_SIZE);
3087
3088 memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf),
3089 &card->token.ulp_connection_r,QETH_MPC_TOKEN_LENGTH);
3090
3091 memcpy(card->send_buf+IPA_PDU_HEADER_SIZE,
3092 cmd,sizeof(ipa_cmd_t));
3093
3094 buffer=qeth_send_control_data(card,card->send_buf,
3095 IPA_PDU_HEADER_SIZE+sizeof(ipa_cmd_t),
3096 ipatype);
3097
3098 if (!buffer) {
3099 if (atomic_read(&card->escape_softsetup)) result=0;
3100 else result=-1;
3101 } else {
3102 reply=(ipa_cmd_t*)PDU_ENCAPSULATION(buffer);
3103 if ((update_cmd)&&(reply)) memcpy(cmd,reply,sizeof(ipa_cmd_t));
3104 result=reply->return_code;
3105
3106 if ((ipa_cmd==IPA_CMD_SETASSPARMS)&&(result==0)) {
3107 result=reply->data.setassparms.return_code;
3108 }
3109 if ((ipa_cmd==IPA_CMD_SETADAPTERPARMS)&&(result==0)) {
3110 result=reply->data.setadapterparms.return_code;
3111 }
3112 if ( (ipa_cmd==IPA_CMD_SETASSPARMS) &&
3113 (result==0) &&
3114 (reply->data.setassparms.assist_no==
3115 IPA_INBOUND_CHECKSUM) &&
3116 (reply->data.setassparms.command_code==
3117 IPA_CMD_ASS_START) ) {
3118 card->csum_enable_mask=
3119 reply->data.setassparms.data.flags_32bit;
3120 }
3121 }
3122 return result;
3123}
3124
3125static void qeth_fill_ipa_cmd(qeth_card_t *card,ipa_cmd_t *cmd,
3126 __u8 command,int ip_vers)
3127{
3128 memset(cmd,0,sizeof(ipa_cmd_t));
3129 cmd->command=command;
3130 cmd->initiator=INITIATOR_HOST;
3131 cmd->seq_no=card->seqno.ipa++;
3132 cmd->adapter_type=qeth_get_adapter_type_for_ipa(card->link_type);
3133 cmd->rel_adapter_no=(__u8)card->options.portno;
3134 cmd->prim_version_no=1;
3135 cmd->param_count=1;
3136 cmd->prot_version=ip_vers;
3137 cmd->ipa_supported=0;
3138 cmd->ipa_enabled=0;
3139}
3140
3141static int qeth_send_startstoplan(qeth_card_t *card,__u8 ipacmd,__u16 ip_vers)
3142{
3143 ipa_cmd_t cmd;
3144 int result;
3145
3146 qeth_fill_ipa_cmd(card,&cmd,ipacmd,0);
3147 cmd.param_count=0;
3148 cmd.prot_version=ip_vers;
3149 cmd.ipa_supported=0;
3150 cmd.ipa_enabled=0;
3151
3152 result=qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE);
3153 return result;
3154}
3155
3156static int qeth_send_startlan(qeth_card_t *card,__u16 ip_vers)
3157{
3158 int result;
3159 char dbf_text[15];
3160
3161 sprintf(dbf_text,"stln%4x",card->irq0);
3162 QETH_DBF_TEXT4(0,trace,dbf_text);
3163
3164 result=qeth_send_startstoplan(card,IPA_CMD_STARTLAN,ip_vers);
3165 if (!result) atomic_set(&card->is_startlaned,1);
3166
3167 if (result) {
3168 QETH_DBF_TEXT2(0,trace,"STRTLNFL");
3169 sprintf(dbf_text,"%4x%4x",card->irq0,result);
3170 QETH_DBF_TEXT2(0,trace,dbf_text);
3171 }
3172
3173 return result;
3174}
3175
3176static int qeth_send_stoplan(qeth_card_t *card)
3177{
3178#ifdef QETH_SEND_STOPLAN_ON_SHUTDOWN
3179 int result;
3180 char dbf_text[15];
3181
3182 atomic_set(&card->is_startlaned,0);
3183
3184 sprintf(dbf_text,"spln%4x",card->irq0);
3185 QETH_DBF_TEXT4(0,trace,dbf_text);
3186
3187 result=qeth_send_startstoplan(card,IPA_CMD_STOPLAN,4);
3188
3189 if (result) {
3190 QETH_DBF_TEXT2(0,trace,"STPLNFLD");
3191 sprintf(dbf_text,"%4x%4x",card->irq0,result);
3192 QETH_DBF_TEXT2(0,trace,dbf_text);
3193 }
3194
3195 return result;
3196#else
3197 return 0;
3198#endif
3199}
3200
3201static int qeth_send_qipassist(qeth_card_t *card,short ip_vers)
3202{
3203 ipa_cmd_t cmd;
3204 int result;
3205
3206 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_QIPASSIST,ip_vers);
3207
3208 result=qeth_send_ipa_cmd(card,&cmd,1,IPA_CMD_STATE);
3209
3210 if (!result) {
3211 if (ip_vers==4) {
3212 card->ipa_supported=cmd.ipa_supported;
3213 card->ipa_enabled=cmd.ipa_enabled;
3214 } else {
3215 card->ipa6_supported=cmd.ipa_supported;
3216 card->ipa6_enabled=cmd.ipa_enabled;
3217 }
3218 }
3219
3220 return result;
3221}
3222
3223static int qeth_send_ipa_arpcmd(qeth_card_t *card,arp_cmd_t *cmd,
3224 int update_cmd,int ipatype,__u32 req_size)
3225{
3226 unsigned char *buffer;
3227 int ipa_cmd;
3228 int result;
3229 __u16 s1,s2;
3230
3231
3232 if ( (cmd->prot_version==6) &&
3233 (!qeth_is_supported(IPA_IPv6)) ) return 0;
3234 result = 0;
3235 ipa_cmd=cmd->command;
3236
3237 memcpy(card->send_buf,IPA_PDU_HEADER,
3238 IPA_PDU_HEADER_SIZE);
3239 memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf),
3240 &card->token.ulp_connection_r,QETH_MPC_TOKEN_LENGTH);
3241 memcpy(card->send_buf+IPA_PDU_HEADER_SIZE,
3242 cmd,sizeof(arp_cmd_t));
3243
3244 if (req_size) {
3245
3246 s1=(__u32)IPA_PDU_HEADER_SIZE+SNMP_BASE_CMDLENGTH+req_size;
3247 s2=(__u32)SNMP_BASE_CMDLENGTH+req_size;
3248 memcpy(QETH_IPA_PDU_LEN_TOTAL(card->send_buf),&s1,2);
3249 memcpy(QETH_IPA_PDU_LEN_PDU1(card->send_buf),&s2,2);
3250 memcpy(QETH_IPA_PDU_LEN_PDU2(card->send_buf),&s2,2);
3251 memcpy(QETH_IPA_PDU_LEN_PDU3(card->send_buf),&s2,2);
3252 }
3253
3254 buffer=qeth_send_control_data(card,card->send_buf,
3255 IPA_PDU_HEADER_SIZE+sizeof(arp_cmd_t),
3256 ipatype);
3257 if (!buffer)
3258 result = -ENODATA;
3259 else
3260 result = card->ioctl_returncode;
3261 return result;
3262}
3263
3264static int qeth_ioctl_handle_snmp_data(qeth_card_t *card,arp_cmd_t *reply)
3265{
3266 __u16 data_len;
3267
3268#define SNMP_HEADER_SIZE_WITH_TOKEN 36
3269
3270 data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(card->dma_stuff->recbuf));
3271
3272 if (reply->data.setadapterparms.frame_seq_no == 1) {
3273 data_len = data_len -
3274 (__u16)((char*)reply->data.setadapterparms.
3275 data.snmp_subcommand.
3276 snmp_data - (char*)reply);
3277 } else {
3278 data_len = data_len -
3279 (__u16)((char*)&reply->data.setadapterparms.data.
3280 snmp_subcommand.
3281 snmp_request - (char*)reply);
3282 }
3283 if (reply->data.setadapterparms.frame_seq_no == 1) {
3284 if (card->ioctl_buffersize <= (SNMP_HEADER_SIZE_WITH_TOKEN +
3285 reply->data.setadapterparms.frames_used_total *
3286 ARP_DATA_SIZE)) {
3287 card->ioctl_returncode = ARP_RETURNCODE_ERROR;
3288 reply->data.setadapterparms.data.
3289 snmp_subcommand.snmp_returncode = -ENOMEM;
3290 } else {
3291 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3292 card->number_of_entries = 0;
3293 memcpy(((char *)card->ioctl_data_buffer),
3294 reply->data.setadapterparms.snmp_token,
3295 SNMP_HEADER_SIZE_WITH_TOKEN);
3296 card->ioctl_buffer_pointer = card->ioctl_data_buffer+
3297 SNMP_HEADER_SIZE_WITH_TOKEN;
3298 }
3299 }
3300
3301 if (card->ioctl_returncode != ARP_RETURNCODE_ERROR &&
3302 reply->data.setadapterparms.frame_seq_no <=
3303 reply->data.setadapterparms.frames_used_total) {
3304 if (reply->data.setadapterparms.return_code==
3305 IPA_REPLY_SUCCESS) {
3306 if (reply->data.setadapterparms.frame_seq_no == 1) {
3307 memcpy(card->ioctl_buffer_pointer,
3308 reply->data.setadapterparms.data.
3309 snmp_subcommand.snmp_data,data_len);
3310 } else {
3311 memcpy(card->ioctl_buffer_pointer,
3312 (char*)&reply->data.setadapterparms.
3313 data.snmp_subcommand.
3314 snmp_request,data_len);
3315 }
3316 card->ioctl_buffer_pointer =
3317 card->ioctl_buffer_pointer + data_len;
3318 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3319
3320 if (reply->data.setadapterparms.frame_seq_no ==
3321 reply->data.setadapterparms.frames_used_total) {
3322 card->ioctl_returncode =
3323 ARP_RETURNCODE_LASTREPLY;
3324 }
3325 } else {
3326 card->ioctl_returncode = ARP_RETURNCODE_ERROR;
3327 memset(card->ioctl_data_buffer,0,
3328 card->ioctl_buffersize);
3329 reply->data.setadapterparms.data.
3330 snmp_subcommand.snmp_returncode =
3331 reply->data.setadapterparms.return_code;
3332 }
3333 }
3334#undef SNMP_HEADER_SIZE_WITH_TOKEN
3335
3336 return card->ioctl_returncode;
3337}
3338
3339static int qeth_ioctl_handle_arp_data(qeth_card_t *card, arp_cmd_t *reply)
3340{
3341 if ( (reply->data.setassparms.command_code==
3342 IPA_CMD_ASS_ARP_SET_NO_ENTRIES) ||
3343 (reply->data.setassparms.command_code==
3344 IPA_CMD_ASS_ARP_ADD_ENTRY) ||
3345 (reply->data.setassparms.command_code==
3346 IPA_CMD_ASS_ARP_REMOVE_ENTRY) ) {
3347 if (reply->data.setassparms.return_code) {
3348 return ARP_RETURNCODE_ERROR;
3349 } else {
3350 return ARP_RETURNCODE_LASTREPLY;
3351 }
3352 }
3353 if (reply->data.setassparms.seq_no == 1) {
3354 if (card->ioctl_buffersize <=
3355 (sizeof(__u16) + sizeof(int) + reply->data.
3356 setassparms.number_of_replies * ARP_DATA_SIZE)) {
3357 card->ioctl_returncode = ARP_RETURNCODE_ERROR;
3358 } else {
3359 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3360 card->number_of_entries = 0;
3361 card->ioctl_buffer_pointer = card->ioctl_data_buffer+
3362 sizeof(__u16) + sizeof(int);
3363 }
3364 }
3365
3366 if (card->ioctl_returncode != ARP_RETURNCODE_ERROR &&
3367 reply->data.setassparms.seq_no <=
3368 reply->data.setassparms.number_of_replies) {
3369
3370 if (reply->data.setassparms.return_code==IPA_REPLY_SUCCESS) {
3371
3372 card->number_of_entries = card->number_of_entries +
3373 reply->data.setassparms.
3374 data.queryarp_data.
3375 number_of_entries;
3376 memcpy(card->ioctl_buffer_pointer,
3377 reply->data.setassparms.data.queryarp_data.
3378 arp_data,ARP_DATA_SIZE);
3379 card->ioctl_buffer_pointer = card->
3380 ioctl_buffer_pointer + ARP_DATA_SIZE;
3381 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3382 if (reply->data.setassparms.seq_no ==
3383 reply->data.setassparms.number_of_replies) {
3384 memcpy(card->ioctl_data_buffer,
3385 &reply->data.setassparms.data.
3386 queryarp_data.osa_setbitmask,
3387 sizeof(__u16));
3388 card->ioctl_returncode=
3389 ARP_RETURNCODE_LASTREPLY;
3390 }
3391 } else {
3392 card->ioctl_returncode = ARP_RETURNCODE_ERROR;
3393 memset(card->ioctl_data_buffer,0,
3394 card->ioctl_buffersize);
3395 }
3396 }
3397 return card->ioctl_returncode;
3398}
3399static int qeth_is_arp_command(int cmd)
3400{
3401 switch (cmd) {
3402 case IPA_CMD_ASS_ARP_SET_NO_ENTRIES:
3403 case IPA_CMD_ASS_ARP_QUERY_CACHE:
3404 case IPA_CMD_ASS_ARP_ADD_ENTRY:
3405 case IPA_CMD_ASS_ARP_REMOVE_ENTRY:
3406 case IPA_CMD_ASS_ARP_FLUSH_CACHE:
3407 case IPA_CMD_ASS_ARP_QUERY_INFO:
3408 case IPA_CMD_ASS_ARP_QUERY_STATS:
3409 return 1;
3410 default:
3411 return 0;
3412 }
3413}
3414
3415static int qeth_look_for_arp_data(qeth_card_t *card)
3416{
3417 arp_cmd_t *reply;
3418 int result;
3419
3420
3421 reply=(arp_cmd_t*)PDU_ENCAPSULATION(card->dma_stuff->recbuf);
3422
3423 if ( (reply->command==IPA_CMD_SETASSPARMS) &&
3424 (reply->data.setassparms.assist_no==IPA_ARP_PROCESSING) &&
3425 (reply->data.setassparms.command_code==
3426 IPA_CMD_ASS_ARP_FLUSH_CACHE) ) {
3427 result=ARP_FLUSH;
3428 } else if ( (reply->command == IPA_CMD_SETASSPARMS) &&
3429 (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) &&
3430 (qeth_is_arp_command(reply->data.setassparms.command_code)) ) {
3431 result = qeth_ioctl_handle_arp_data(card,reply);
3432 } else if ( (reply->command == IPA_CMD_SETADAPTERPARMS) &&
3433 (reply->data.setadapterparms.command_code ==
3434 IPA_SETADP_SET_SNMP_CONTROL) &&
3435 (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS) ){
3436 result = qeth_ioctl_handle_snmp_data(card,reply);
3437 } else
3438 result = ARP_RETURNCODE_NOARPDATA;
3439
3440 return result;
3441}
3442
3443
3444
3445static int qeth_queryarp(qeth_card_t *card,struct ifreq *req,int version,
3446 __u32 assist_no, __u16 command_code,char *c_data,
3447 __u16 len)
3448{
3449 int data_size;
3450 arp_cmd_t *cmd;
3451 int result;
3452
3453
3454 cmd = (arp_cmd_t *) kmalloc(sizeof(arp_cmd_t),GFP_KERNEL);
3455 if (!cmd) {
3456 return IPA_REPLY_FAILED;
3457 }
3458
3459 memcpy(&data_size,c_data,sizeof(int));
3460
3461 qeth_fill_ipa_cmd(card,(ipa_cmd_t*)cmd,IPA_CMD_SETASSPARMS,version);
3462
3463 cmd->data.setassparms.assist_no=assist_no;
3464 cmd->data.setassparms.length=8+len;
3465 cmd->data.setassparms.command_code=command_code;
3466 cmd->data.setassparms.return_code=0;
3467 cmd->data.setassparms.seq_no=0;
3468
3469 card->ioctl_buffersize = data_size;
3470 card->ioctl_data_buffer = (char *) vmalloc(data_size);
3471 if (!card->ioctl_data_buffer) {
3472 kfree(cmd);
3473 return IPA_REPLY_FAILED;
3474 }
3475
3476 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3477
3478 result=qeth_send_ipa_arpcmd(card,cmd,1,IPA_IOCTL_STATE,0);
3479
3480 if ((result == ARP_RETURNCODE_ERROR) ||
3481 (result == -ENODATA)) {
3482 result = IPA_REPLY_FAILED;
3483 }
3484 else {
3485 result = IPA_REPLY_SUCCESS;
3486 memcpy(((char *)(card->ioctl_data_buffer)) + sizeof(__u16),
3487 &(card->number_of_entries),sizeof(int));
3488 if (copy_to_user(req->ifr_ifru.ifru_data,
3489 card->ioctl_data_buffer,data_size))
3490 result =-EFAULT;
3491 }
3492 card->ioctl_buffer_pointer = NULL;
3493 vfree(card->ioctl_data_buffer);
3494 kfree(cmd);
3495 card->number_of_entries = 0;
3496 card->ioctl_buffersize = 0;
3497
3498 return result;
3499}
3500
3501static int snmp_set_setadapterparms_command(qeth_card_t *card,
3502 arp_cmd_t *cmd,struct ifreq *req,
3503 char *data,__u16 len,
3504 __u16 command_code,int req_size)
3505{
3506 __u32 data_size;
3507
3508 memcpy(&data_size,data,sizeof(__u32));
3509
3510 card->ioctl_buffersize = data_size;
3511 card->ioctl_data_buffer = (char *) vmalloc(data_size);
3512 if (!card->ioctl_data_buffer) {
3513 return -ENOMEM;
3514 }
3515 card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
3516
3517 memcpy(cmd->data.setadapterparms.snmp_token,
3518 data+SNMP_REQUEST_DATA_OFFSET,req_size);
3519
3520 cmd->data.setadapterparms.cmdlength=SNMP_SETADP_CMDLENGTH+req_size;
3521 cmd->data.setadapterparms.command_code = command_code;
3522 cmd->data.setadapterparms.frames_used_total=1;
3523 cmd->data.setadapterparms.frame_seq_no=1;
3524
3525 return 0;
3526}
3527
3528static int qeth_send_snmp_control(qeth_card_t *card,struct ifreq *req,
3529 __u32 command,__u16 command_code,
3530 char *c_data,__u16 len)
3531{
3532 arp_cmd_t *cmd;
3533 __u32 result,req_size;
3534
3535 cmd = (arp_cmd_t *) kmalloc(sizeof(arp_cmd_t),GFP_KERNEL);
3536 if (!cmd) {
3537 return IPA_REPLY_FAILED;
3538 }
3539
3540 qeth_fill_ipa_cmd(card,(ipa_cmd_t*)cmd,command,4);
3541
3542 memcpy(&req_size,((char*)c_data)+sizeof(__u32),sizeof(__u32));
3543
3544 if (snmp_set_setadapterparms_command(card,cmd,req,c_data,
3545 len,command_code,req_size))
3546 {
3547 kfree(cmd);
3548 return IPA_REPLY_FAILED;
3549 }
3550
3551 result=qeth_send_ipa_arpcmd(card,cmd,1,IPA_IOCTL_STATE,req_size);
3552
3553 if (result == -ENODATA) {
3554 result = IPA_REPLY_FAILED;
3555 goto snmp_out;
3556 }
3557 if (result == ARP_RETURNCODE_ERROR )
3558 result = IPA_REPLY_FAILED;
3559 else
3560 result = IPA_REPLY_SUCCESS;
3561
3562 if (copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
3563 card->ioctl_data_buffer, card->ioctl_buffersize))
3564 result = -EFAULT;
3565snmp_out:
3566 card->number_of_entries = 0;
3567 card->ioctl_buffersize = 0;
3568 card->ioctl_buffer_pointer = NULL;
3569 vfree(card->ioctl_data_buffer);
3570 kfree(cmd);
3571
3572 return result;
3573}
3574
3575static int qeth_send_setassparms(qeth_card_t *card,int version,
3576 __u32 assist_no,__u16 command_code,
3577 long data,__u16 len)
3578{
3579 ipa_cmd_t cmd;
3580 int result;
3581
3582 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_SETASSPARMS,version);
3583
3584 cmd.data.setassparms.assist_no=assist_no;
3585 cmd.data.setassparms.length=8+len;
3586 cmd.data.setassparms.command_code=command_code;
3587 cmd.data.setassparms.return_code=0;
3588 cmd.data.setassparms.seq_no=0;
3589
3590 if (len<=sizeof(__u32))
3591 cmd.data.setassparms.data.flags_32bit=(__u32)data;
3592 else if (len>sizeof(__u32))
3593 memcpy(&cmd.data.setassparms.data,(void*)data,
3594
3595 qeth_min(len,PAGE_SIZE));
3596 if (command_code != IPA_CMD_ASS_START) {
3597 result=qeth_send_ipa_cmd(card,&cmd,0,
3598 ((assist_no==IPA_ARP_PROCESSING)&&
3599 (command_code!=IPA_CMD_ASS_ARP_FLUSH_CACHE))?
3600 IPA_IOCTL_STATE:IPA_CMD_STATE);
3601
3602 } else
3603 result=qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE);
3604
3605 return result;
3606}
3607
3608static int qeth_send_setadapterparms_query(qeth_card_t *card)
3609{
3610 ipa_cmd_t cmd;
3611 int result;
3612
3613 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_SETADAPTERPARMS,
3614 IPA_SETADAPTERPARMS_IP_VERSION);
3615 cmd.data.setadapterparms.cmdlength=sizeof(struct ipa_setadp_cmd);
3616 cmd.data.setadapterparms.command_code=
3617 IPA_SETADP_QUERY_COMMANDS_SUPPORTED;
3618 cmd.data.setadapterparms.frames_used_total=1;
3619 cmd.data.setadapterparms.frame_seq_no=1;
3620 result=qeth_send_ipa_cmd(card,&cmd,1,IPA_CMD_STATE);
3621
3622 if (cmd.data.setadapterparms.data.query_cmds_supp.lan_type&0x7f)
3623 card->link_type=cmd.data.setadapterparms.data.
3624 query_cmds_supp.lan_type;
3625
3626 card->adp_supported=
3627 cmd.data.setadapterparms.data.query_cmds_supp.supported_cmds;
3628
3629 return result;
3630}
3631
3632static int qeth_send_setadapterparms_mode(qeth_card_t *card,__u32 command,
3633 __u32 mode)
3634{
3635 ipa_cmd_t cmd;
3636 int result;
3637
3638 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_SETADAPTERPARMS,
3639 IPA_SETADAPTERPARMS_IP_VERSION);
3640 cmd.data.setadapterparms.cmdlength=sizeof(struct ipa_setadp_cmd);
3641 cmd.data.setadapterparms.command_code=command;
3642 cmd.data.setadapterparms.frames_used_total=1;
3643 cmd.data.setadapterparms.frame_seq_no=1;
3644 cmd.data.setadapterparms.data.mode=mode;
3645 result=qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE);
3646
3647 return result;
3648}
3649
3650static int qeth_send_setadapterparms_change_addr(qeth_card_t *card,
3651 __u32 command,
3652 __u32 subcmd,__u8 *mac_addr,
3653 int addr_len)
3654{
3655 ipa_cmd_t cmd;
3656 int result;
3657
3658 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_SETADAPTERPARMS,
3659 IPA_SETADAPTERPARMS_IP_VERSION);
3660 cmd.data.setadapterparms.cmdlength=sizeof(struct ipa_setadp_cmd);
3661 cmd.data.setadapterparms.command_code=command;
3662 cmd.data.setadapterparms.frames_used_total=1;
3663 cmd.data.setadapterparms.frame_seq_no=1;
3664 cmd.data.setadapterparms.data.change_addr.cmd=subcmd;
3665 cmd.data.setadapterparms.data.change_addr.addr_size=addr_len;
3666 memcpy(&cmd.data.setadapterparms.data.change_addr.addr,
3667 mac_addr,addr_len);
3668
3669 result=qeth_send_ipa_cmd(card,&cmd,1,IPA_CMD_STATE);
3670
3671 memcpy(mac_addr,&cmd.data.setadapterparms.data.change_addr.addr,
3672 addr_len);
3673
3674 return result;
3675}
3676
3677static int qeth_send_setassparms_simple_with_data(qeth_card_t *card,
3678 __u32 assist_no,
3679 __u16 command_code,
3680 long data)
3681{
3682 return qeth_send_setassparms(card,4,assist_no,command_code,data,4);
3683}
3684
3685static int qeth_send_setassparms_simple_without_data(qeth_card_t *card,
3686 __u32 assist_no,
3687 __u16 command_code)
3688{
3689 return qeth_send_setassparms(card,4,assist_no,command_code,0,0);
3690}
3691
3692static int qeth_send_setassparms_simple_without_data6(qeth_card_t *card,
3693 __u32 assist_no,
3694 __u16 command_code)
3695{
3696 return qeth_send_setassparms(card,6,assist_no,command_code,0,0);
3697}
3698
3699static int qeth_send_setdelip(qeth_card_t *card,__u8 *ip,__u8 *netmask,
3700 int ipacmd,short ip_vers,unsigned int flags)
3701{
3702 ipa_cmd_t cmd;
3703 int ip_len=(ip_vers==6)?16:4;
3704
3705 qeth_fill_ipa_cmd(card,&cmd,ipacmd,ip_vers);
3706 if (ip_vers==6) {
3707 memcpy(&cmd.data.setdelip6.ip,ip,ip_len);
3708 memcpy(&cmd.data.setdelip6.netmask,netmask,ip_len);
3709 cmd.data.setdelip6.flags=flags;
3710 } else {
3711 memcpy(&cmd.data.setdelip4.ip,ip,ip_len);
3712 memcpy(&cmd.data.setdelip4.netmask,netmask,ip_len);
3713 cmd.data.setdelip4.flags=flags;
3714 }
3715
3716 return qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE|
3717 ((ipacmd==IPA_CMD_SETIP)?IPA_SETIP_FLAG:0));
3718}
3719
3720static int qeth_send_setdelipm(qeth_card_t *card,__u8 *ip,__u8 *mac,
3721 int ipacmd,short ip_vers)
3722{
3723 ipa_cmd_t cmd;
3724 int ip_len=(ip_vers==6)?16:4;
3725
3726 qeth_fill_ipa_cmd(card,&cmd,ipacmd,ip_vers);
3727 memcpy(&cmd.data.setdelipm.mac,mac,6);
3728 if (ip_vers==6) {
3729 memcpy(&cmd.data.setdelipm.ip6,ip,ip_len);
3730 } else {
3731 memcpy(&cmd.data.setdelipm.ip4_6,ip,ip_len);
3732 }
3733
3734 return qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE|
3735 ((ipacmd==IPA_CMD_SETIPM)?IPA_SETIP_FLAG:0));
3736}
3737
3738#define PRINT_SETIP_ERROR(x) \
3739 if (result) \
3740 PRINT_ERR("setip%c: return code 0x%x (%s)\n",x,result, \
3741 (result==0xe002)?"invalid mtu size": \
3742 (result==0xe005)?"duplicate ip address": \
3743 (result==0xe0a5)?"duplicate ip address": \
3744 (result==0xe006)?"ip table full": \
3745 (result==0xe008)?"startlan not received": \
3746 (result==0xe009)?"setip already received": \
3747 (result==0xe00a)?"dup network ip address": \
3748 (result==0xe00b)?"mblk no free main task entry": \
3749 (result==0xe00d)?"invalid ip version": \
3750 (result==0xe00e)?"unsupported arp assist cmd": \
3751 (result==0xe00f)?"arp assist not enabled": \
3752 (result==0xe080)?"startlan disabled": \
3753 (result==0xf012)?"unicast IP address invalid": \
3754 (result==0xf013)?"multicast router limit reached": \
3755 (result==0xf014)?"stop assist not supported": \
3756 (result==0xf015)?"multicast assist not set": \
3757 (result==0xf080)?"VM: startlan disabled": \
3758 (result==-1)?"IPA communication timeout": \
3759 "unknown return code")
3760
3761static inline int qeth_send_setip(qeth_card_t *card,__u8 *ip,
3762 __u8 *netmask,short ip_vers,int use_retries)
3763{
3764 int result;
3765 int retries;
3766 char dbf_text[15];
3767 int takeover=0;
3768
3769 retries=(use_retries)?QETH_SETIP_RETRIES:1;
3770 if (qeth_is_ipa_covered_by_ipato_entries(ip_vers,ip,card)) {
3771 sprintf(dbf_text,"ipto%4x",card->irq0);
3772 QETH_DBF_TEXT2(0,trace,dbf_text);
3773 if (ip_vers==4) {
3774 *((__u32*)(&dbf_text[0]))=*((__u32*)ip);
3775 *((__u32*)(&dbf_text[4]))=*((__u32*)netmask);
3776 QETH_DBF_HEX2(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
3777 } else {
3778 QETH_DBF_HEX2(0,trace,ip,QETH_DBF_TRACE_LEN);
3779 QETH_DBF_HEX2(0,trace,ip+QETH_DBF_TRACE_LEN,
3780 QETH_DBF_TRACE_LEN);
3781 QETH_DBF_HEX2(0,trace,netmask,QETH_DBF_TRACE_LEN);
3782 QETH_DBF_HEX2(0,trace,netmask+QETH_DBF_TRACE_LEN,
3783 QETH_DBF_TRACE_LEN);
3784 }
3785 takeover=1;
3786 }
3787retry:
3788 result=qeth_send_setdelip(card,ip,netmask,IPA_CMD_SETIP,ip_vers,
3789 (takeover)?IPA_SETIP_TAKEOVER_FLAGS:
3790 IPA_SETIP_FLAGS);
3791 PRINT_SETIP_ERROR(' ');
3792
3793 if (result) {
3794 QETH_DBF_TEXT2(0,trace,"SETIPFLD");
3795 sprintf(dbf_text,"%4x%4x",card->irq0,result);
3796 QETH_DBF_TEXT2(0,trace,dbf_text);
3797 }
3798
3799 if ( ((result==-1)||(result==0xe080)||(result==0xf080))&&
3800 (retries--) ) {
3801 sprintf(dbf_text,"sipr%4x",card->irq0);
3802 QETH_DBF_TEXT2(0,trace,dbf_text);
3803 if (ip_vers==4) {
3804 *((__u32*)(&dbf_text[0]))=*((__u32*)ip);
3805 *((__u32*)(&dbf_text[4]))=*((__u32*)netmask);
3806 QETH_DBF_HEX2(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
3807 } else {
3808 QETH_DBF_HEX2(0,trace,ip,QETH_DBF_TRACE_LEN);
3809 QETH_DBF_HEX2(0,trace,ip+QETH_DBF_TRACE_LEN,
3810 QETH_DBF_TRACE_LEN);
3811 QETH_DBF_HEX2(0,trace,netmask,QETH_DBF_TRACE_LEN);
3812 QETH_DBF_HEX2(0,trace,netmask+QETH_DBF_TRACE_LEN,
3813 QETH_DBF_TRACE_LEN);
3814 }
3815 PRINT_WARN("trying again...\n");
3816 goto retry;
3817 }
3818
3819 return result;
3820}
3821
3822static inline int qeth_send_delip(qeth_card_t *card,__u8 *ip,
3823 __u8 *netmask,short ip_vers)
3824{
3825 return qeth_send_setdelip(card,ip,netmask,IPA_CMD_DELIP,ip_vers,
3826 IPA_DELIP_FLAGS);
3827}
3828
3829static inline int qeth_send_setipm(qeth_card_t *card,__u8 *ip,
3830 __u8 *mac,short ip_vers,int use_retries)
3831{
3832 int result;
3833 int retries;
3834 char dbf_text[15];
3835
3836 retries=(use_retries)?QETH_SETIP_RETRIES:1;
3837 if (qeth_is_ipa_covered_by_ipato_entries(ip_vers,ip,card)) {
3838 sprintf(dbf_text,"imto%4x",card->irq0);
3839 QETH_DBF_TEXT2(0,trace,dbf_text);
3840 if (ip_vers==4) {
3841 *((__u32*)(&dbf_text[0]))=*((__u32*)ip);
3842 QETH_DBF_HEX2(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
3843 } else {
3844 QETH_DBF_HEX2(0,trace,ip,QETH_DBF_TRACE_LEN);
3845 QETH_DBF_HEX2(0,trace,ip+QETH_DBF_TRACE_LEN,
3846 QETH_DBF_TRACE_LEN);
3847 }
3848 }
3849
3850retry:
3851 result=qeth_send_setdelipm(card,ip,mac,IPA_CMD_SETIPM,ip_vers);
3852 PRINT_SETIP_ERROR('m');
3853
3854 if (result) {
3855 QETH_DBF_TEXT2(0,trace,"SETIMFLD");
3856 sprintf(dbf_text,"%4x%4x",card->irq0,result);
3857 QETH_DBF_TEXT2(0,trace,dbf_text);
3858 }
3859
3860 if ((result==-1)&&(retries--)) {
3861 sprintf(dbf_text,"simr%4x",card->irq0);
3862 QETH_DBF_TEXT2(0,trace,dbf_text);
3863 if (ip_vers==4) {
3864 sprintf(dbf_text,"%08x",*((__u32*)ip));
3865 QETH_DBF_TEXT2(0,trace,dbf_text);
3866 } else {
3867 QETH_DBF_HEX2(0,trace,ip,QETH_DBF_TRACE_LEN);
3868 QETH_DBF_HEX2(0,trace,ip+QETH_DBF_TRACE_LEN,
3869 QETH_DBF_TRACE_LEN);
3870 }
3871 QETH_DBF_HEX2(0,trace,mac,OSA_ADDR_LEN);
3872 PRINT_WARN("trying again...\n");
3873 goto retry;
3874 }
3875
3876 return result;
3877}
3878
3879static inline int qeth_send_delipm(qeth_card_t *card,__u8 *ip,
3880 __u8 *mac,short ip_vers)
3881{
3882 return qeth_send_setdelipm(card,ip,mac,IPA_CMD_DELIPM,ip_vers);
3883}
3884
3885static int qeth_add_vipa_entry(qeth_card_t *card,int version,__u8 *addr,
3886 int flag)
3887{
3888 qeth_vipa_entry_t *entry,*e;
3889 int result=0;
3890
3891 entry=(qeth_vipa_entry_t*)kmalloc(sizeof(qeth_vipa_entry_t),
3892 GFP_KERNEL);
3893 if (!entry) {
3894 PRINT_ERR("not enough memory for vipa handling\n");
3895 return -ENOMEM;
3896 }
3897 entry->version=version;
3898 entry->flag=flag;
3899 memcpy(entry->ip,addr,16);
3900 entry->state=VIPA_2_B_ADDED;
3901
3902 my_write_lock(&card->vipa_list_lock);
3903 e=card->vipa_list;
3904 while (e) {
3905 if (e->version!=version) goto next;
3906 if (memcmp(e->ip,addr,(version==4)?4:16)) goto next;
3907 if (flag==IPA_SETIP_VIPA_FLAGS) {
3908 PRINT_ERR("vipa already set\n");
3909 } else {
3910 PRINT_ERR("rxip already set\n");
3911 }
3912 kfree(entry);
3913 result=-EALREADY;
3914 goto out;
3915next:
3916 e=e->next;
3917 }
3918 entry->next=card->vipa_list;
3919 card->vipa_list=entry;
3920out:
3921 my_write_unlock(&card->vipa_list_lock);
3922 return result;
3923}
3924
3925static int qeth_del_vipa_entry(qeth_card_t *card,int version,__u8 *addr,
3926 int flag)
3927{
3928 qeth_vipa_entry_t *e;
3929 int result=0;
3930
3931 my_write_lock(&card->vipa_list_lock);
3932 e=card->vipa_list;
3933 while (e) {
3934 if (e->version!=version) goto next;
3935 if (e->flag!=flag) goto next;
3936 if (memcmp(e->ip,addr,(version==4)?4:16)) goto next;
3937 e->state=VIPA_2_B_REMOVED;
3938 goto out;
3939next:
3940 e=e->next;
3941 }
3942 if (flag==IPA_SETIP_VIPA_FLAGS) {
3943 PRINT_ERR("vipa not found\n");
3944 } else {
3945 PRINT_ERR("rxip not found\n");
3946 }
3947 result=-ENOENT;
3948out:
3949 my_write_unlock(&card->vipa_list_lock);
3950 return result;
3951}
3952
3953static void qeth_set_vipas(qeth_card_t *card,int set_only)
3954{
3955 qeth_vipa_entry_t *e,*le=NULL,*ne;
3956
3957 char dbf_text[15];
3958 int result;
3959 __u8 netmask[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3960 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
3961 qeth_vipa_entry_t *priv_add_list=NULL;
3962 qeth_vipa_entry_t *priv_del_list=NULL;
3963
3964 my_write_lock(&card->vipa_list_lock);
3965 e=card->vipa_list;
3966 while (e) {
3967 switch (e->state) {
3968 case VIPA_2_B_ADDED:
3969 if (!set_only) break;
3970 if (!atomic_read(&card->is_open)) break;
3971
3972
3973 ne=(qeth_vipa_entry_t*)
3974 kmalloc(sizeof(qeth_vipa_entry_t),
3975 GFP_KERNEL);
3976 if (ne) {
3977 ne->version=e->version;
3978 ne->flag=e->flag;
3979 memcpy(ne->ip,e->ip,16);
3980 ne->next=priv_add_list;
3981 priv_add_list=ne;
3982
3983 e->state=VIPA_ESTABLISHED;
3984 } else {
3985 PRINT_ERR("not enough for internal vipa " \
3986 "handling... trying to set " \
3987 "vipa next time.\n");
3988 qeth_start_softsetup_thread(card);
3989 }
3990 break;
3991 case VIPA_2_B_REMOVED:
3992 if (set_only) break;
3993 if (le)
3994 le->next=e->next;
3995 else card->vipa_list=e->next;
3996 ne=e->next;
3997 e->next=priv_del_list;
3998 priv_del_list=e;
3999 e=ne;
4000 continue;
4001 case VIPA_ESTABLISHED:
4002 if (atomic_read(&card->is_open)) break;
4003
4004
4005 ne=(qeth_vipa_entry_t*)
4006 kmalloc(sizeof(qeth_vipa_entry_t),
4007 GFP_KERNEL);
4008 if (ne) {
4009 ne->version=e->version;
4010 ne->flag=e->flag;
4011 memcpy(ne->ip,e->ip,16);
4012 ne->next=priv_del_list;
4013 priv_del_list=ne;
4014
4015 e->state=VIPA_2_B_ADDED;
4016 } else {
4017 PRINT_ERR("not enough for internal vipa " \
4018 "handling... VIPA/RXIP remains set " \
4019 "although device is stopped.\n");
4020 qeth_start_softsetup_thread(card);
4021 }
4022 break;
4023 default:
4024 break;
4025 }
4026 le=e;
4027 e=e->next;
4028 }
4029 my_write_unlock(&card->vipa_list_lock);
4030
4031 while (priv_add_list) {
4032 result=qeth_send_setdelip(card,priv_add_list->ip,netmask,
4033 IPA_CMD_SETIP,priv_add_list->version,
4034 priv_add_list->flag);
4035 PRINT_SETIP_ERROR('s');
4036
4037 if (result) {
4038 QETH_DBF_TEXT2(0,trace,"SETSVFLD");
4039 sprintf(dbf_text,"%4x%4x",card->irq0,result);
4040 QETH_DBF_TEXT2(0,trace,dbf_text);
4041 if (priv_add_list->version==4) {
4042 PRINT_ERR("going to leave vipa/rxip x%08x " \
4043 "unset...\n",
4044 *((__u32*)&priv_add_list->ip[0]));
4045 sprintf(dbf_text,"%08x",
4046 *((__u32*)&priv_add_list->ip[0]));
4047 QETH_DBF_TEXT2(0,trace,dbf_text);
4048 } else {
4049 PRINT_ERR("going to leave vipa/rxip " \
4050 "%08x%08x%08x%08x unset...\n",
4051 *((__u32*)&priv_add_list->ip[0]),
4052 *((__u32*)&priv_add_list->ip[4]),
4053 *((__u32*)&priv_add_list->ip[8]),
4054 *((__u32*)&priv_add_list->ip[12]));
4055 QETH_DBF_HEX2(0,trace,&priv_add_list->ip[0],
4056 QETH_DBF_TRACE_LEN);
4057 QETH_DBF_HEX2(0,trace,&priv_add_list->ip[8],
4058 QETH_DBF_TRACE_LEN);
4059 }
4060 }
4061 e=priv_add_list;
4062 priv_add_list=priv_add_list->next;
4063 kfree(e);
4064 }
4065
4066 while (priv_del_list) {
4067 result=qeth_send_setdelip(card,priv_del_list->ip,netmask,
4068 IPA_CMD_DELIP,priv_del_list->version,
4069 priv_del_list->flag);
4070 if (result) {
4071 QETH_DBF_TEXT2(0,trace,"DELSVFLD");
4072 sprintf(dbf_text,"%4x%4x",card->irq0,result);
4073 QETH_DBF_TEXT2(0,trace,dbf_text);
4074 if (priv_del_list->version==4) {
4075 PRINT_ERR("could not delete vipa/rxip " \
4076 "%08x...\n",
4077 *((__u32*)&priv_del_list->ip[0]));
4078 sprintf(dbf_text,"%08x",
4079 *((__u32*)&priv_del_list->ip[0]));
4080 QETH_DBF_TEXT2(0,trace,dbf_text);
4081 } else {
4082 PRINT_ERR("could not delete vipa/rxip " \
4083 "%08x%08x%08x%08x...\n",
4084 *((__u32*)&priv_del_list->ip[0]),
4085 *((__u32*)&priv_del_list->ip[4]),
4086 *((__u32*)&priv_del_list->ip[8]),
4087 *((__u32*)&priv_del_list->ip[12]));
4088 QETH_DBF_HEX2(0,trace,&priv_del_list->ip[0],
4089 QETH_DBF_TRACE_LEN);
4090 QETH_DBF_HEX2(0,trace,&priv_del_list->ip[8],
4091 QETH_DBF_TRACE_LEN);
4092 }
4093 }
4094 e=priv_del_list;
4095 priv_del_list=priv_del_list->next;
4096 kfree(e);
4097 }
4098}
4099
4100static void qeth_refresh_vipa_states(qeth_card_t *card)
4101{
4102 qeth_vipa_entry_t *e;
4103
4104 my_write_lock(&card->vipa_list_lock);
4105 e=card->vipa_list;
4106 while (e) {
4107 if (e->state==VIPA_ESTABLISHED) e->state=VIPA_2_B_ADDED;
4108 e=e->next;
4109 }
4110 my_write_unlock(&card->vipa_list_lock);
4111}
4112
4113static inline int qeth_send_setrtg(qeth_card_t *card,int routing_type,
4114 short ip_vers)
4115{
4116 ipa_cmd_t cmd;
4117
4118 qeth_fill_ipa_cmd(card,&cmd,IPA_CMD_SETRTG,ip_vers);
4119
4120 cmd.data.setrtg.type=(routing_type)&(ROUTER_MASK);
4121
4122 return qeth_send_ipa_cmd(card,&cmd,0,IPA_CMD_STATE);
4123}
4124
4125static int qeth_is_ipa_in_list(struct in_ifaddr *ip,struct in_ifaddr *list)
4126{
4127 while (list) {
4128 if (ip->ifa_address==list->ifa_address) return 1;
4129 list=list->ifa_next;
4130 }
4131 return 0;
4132}
4133
4134#ifdef QETH_IPV6
4135static int qeth_is_ipa_in_list6(struct inet6_ifaddr *ip,
4136 struct inet6_ifaddr *list)
4137{
4138 while (list) {
4139 if (!memcmp(&ip->addr.s6_addr,&list->addr.s6_addr,16))
4140 return 1;
4141 list=list->if_next;
4142 }
4143 return 0;
4144}
4145
4146static int qeth_add_ifa6_to_list(struct inet6_ifaddr **list,
4147 struct inet6_ifaddr *ifa)
4148{
4149 struct inet6_ifaddr *i;
4150
4151 if (*list==NULL) {
4152 *list=ifa;
4153 } else {
4154 if (qeth_is_ipa_in_list6(ifa,*list))
4155 return -EALREADY;
4156 i=*list;
4157 while (i->if_next) {
4158 i=i->if_next;
4159 }
4160 i->if_next=ifa;
4161 }
4162 ifa->if_next=NULL;
4163 return 0;
4164}
4165#endif
4166
4167static int qeth_add_ifa_to_list(struct in_ifaddr **list,struct in_ifaddr *ifa)
4168{
4169 struct in_ifaddr *i;
4170
4171 if (*list==NULL) {
4172 *list=ifa;
4173 } else {
4174 if (qeth_is_ipa_in_list(ifa,*list))
4175 return -EALREADY;
4176 i=*list;
4177 while (i->ifa_next) {
4178 i=i->ifa_next;
4179 }
4180 i->ifa_next=ifa;
4181 }
4182 ifa->ifa_next=NULL;
4183 return 0;
4184}
4185
4186static int qeth_setips(qeth_card_t *card,int use_setip_retries)
4187{
4188 struct in_ifaddr *addr;
4189 int result;
4190 char dbf_text[15];
4191#ifdef QETH_IPV6
4192 struct inet6_ifaddr *addr6;
4193 __u8 netmask[16];
4194#endif
4195
4196 sprintf(dbf_text,"stip%4x",card->irq0);
4197 QETH_DBF_TEXT3(0,trace,dbf_text);
4198
4199 addr=card->ip_current_state.ip_ifa;
4200 while (addr) {
4201 if (!qeth_is_ipa_in_list(addr,card->ip_new_state.ip_ifa)) {
4202 QETH_DBF_TEXT3(0,trace,"setipdel");
4203 *((__u32*)(&dbf_text[0]))=*((__u32*)&addr->ifa_address);
4204 *((__u32*)(&dbf_text[4]))=*((__u32*)&addr->ifa_mask);
4205 QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
4206 result=qeth_send_delip(card,(__u8*)&addr->ifa_address,
4207 (__u8*)&addr->ifa_mask,4);
4208 if (result) {
4209 PRINT_ERR("was not able to delete ip " \
4210 "%08x/%08x on irq x%x " \
4211 "(result: 0x%x), " \
4212 "trying to continue\n",
4213 addr->ifa_address,
4214 addr->ifa_mask,card->irq0,result);
4215 sprintf(dbf_text,"stdl%4x",result);
4216 QETH_DBF_TEXT3(0,trace,dbf_text);
4217 }
4218 }
4219 addr=addr->ifa_next;
4220 }
4221
4222 addr=card->ip_new_state.ip_ifa;
4223 while (addr) {
4224 if (!qeth_is_ipa_in_list(addr,
4225 card->ip_current_state.ip_ifa)) {
4226 QETH_DBF_TEXT3(0,trace,"setipset");
4227 *((__u32*)(&dbf_text[0]))=
4228 *((__u32*)&addr->ifa_address);
4229 *((__u32*)(&dbf_text[4]))=
4230 *((__u32*)&addr->ifa_mask);
4231 QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN);
4232 result=qeth_send_setip(card,(__u8*)&addr->ifa_address,
4233 (__u8*)&addr->ifa_mask,4,
4234 use_setip_retries);
4235 if (result) {
4236 PRINT_ERR("was not able to set ip " \
4237 "%08x/%08x on irq x%x, trying to " \
4238 "continue\n",
4239 addr->ifa_address,
4240 addr->ifa_mask,card->irq0);
4241 sprintf(dbf_text,"stst%4x",result);
4242 QETH_DBF_TEXT3(0,trace,dbf_text);
4243 }
4244 }
4245 addr=addr->ifa_next;
4246 }
4247
4248#ifdef QETH_IPV6
4249#define FILL_NETMASK(len) { \
4250 int i,j; \
4251 for (i=0;i<16;i++) { \
4252 j=(len)-(i*8); \
4253 if (j>=8) netmask[i]=0xff; else \
4254 if (j<=0) netmask[i]=0x0; else \
4255 netmask[i]=(__u8)(0xFF00>>j); \
4256 } \
4257}
4258
4259 addr6=card->ip_current_state.ip6_ifa;
4260 while (addr6) {
4261 if (!qeth_is_ipa_in_list6(addr6,card->ip_new_state.ip6_ifa)) {
4262 QETH_DBF_TEXT3(0,trace,"setipdl6");
4263 QETH_DBF_HEX3(0,trace,&addr6->addr.s6_addr,
4264 QETH_DBF_TRACE_LEN);
4265 QETH_DBF_HEX3(0,trace,
4266 ((char *)(&addr6->addr.s6_addr))+
4267 QETH_DBF_TRACE_LEN,QETH_DBF_TRACE_LEN);
4268 sprintf(dbf_text,"nmsk%4u",addr6->prefix_len);
4269 QETH_DBF_TEXT3(0,trace,dbf_text);
4270 FILL_NETMASK(addr6->prefix_len);
4271 result=qeth_send_delip(card,
4272 (__u8*)&addr6->addr.s6_addr,
4273 (__u8*)&netmask,6);
4274 if (result) {
4275 PRINT_ERR("was not able to delete ip " \
4276 "%04x:%04x:%04x:%04x:%04x:%04x:" \
4277 "%04x:%04x/%u on irq x%x " \
4278 "(result: 0x%x), " \
4279 "trying to continue\n",
4280 addr6->addr.s6_addr16[0],
4281 addr6->addr.s6_addr16[1],
4282 addr6->addr.s6_addr16[2],
4283 addr6->addr.s6_addr16[3],
4284 addr6->addr.s6_addr16[4],
4285 addr6->addr.s6_addr16[5],
4286 addr6->addr.s6_addr16[6],
4287 addr6->addr.s6_addr16[7],
4288 addr6->prefix_len,
4289 card->irq0,result);
4290 sprintf(dbf_text,"std6%4x",result);
4291 QETH_DBF_TEXT3(0,trace,dbf_text);
4292 }
4293 }
4294 addr6=addr6->if_next;
4295 }
4296
4297 addr6=card->ip_new_state.ip6_ifa;
4298 while (addr6) {
4299 if (!qeth_is_ipa_in_list6(addr6,
4300 card->ip_current_state.ip6_ifa)) {
4301 QETH_DBF_TEXT3(0,trace,"setipst6");
4302 QETH_DBF_HEX3(0,trace,&addr6->addr.s6_addr,
4303 QETH_DBF_TRACE_LEN);
4304 QETH_DBF_HEX3(0,trace,
4305 ((char *)(&addr6->addr.s6_addr))+
4306 QETH_DBF_TRACE_LEN,QETH_DBF_TRACE_LEN);
4307 sprintf(dbf_text,"nmsk%4u",addr6->prefix_len);
4308 QETH_DBF_TEXT3(0,trace,dbf_text);
4309 FILL_NETMASK(addr6->prefix_len);
4310 result=qeth_send_setip(card,
4311 (__u8*)&addr6->addr.s6_addr,
4312 (__u8*)&netmask,6,
4313 use_setip_retries);
4314 if (result) {
4315 PRINT_ERR("was not able to set ip " \
4316 "%04x:%04x:%04x:%04x:%04x:%04x:" \
4317 "%04x:%04x/%u on irq x%x " \
4318 "(result: 0x%x), " \
4319 "trying to continue\n",
4320 addr6->addr.s6_addr16[0],
4321 addr6->addr.s6_addr16[1],
4322 addr6->addr.s6_addr16[2],
4323 addr6->addr.s6_addr16[3],
4324 addr6->addr.s6_addr16[4],
4325 addr6->addr.s6_addr16[5],
4326 addr6->addr.s6_addr16[6],
4327 addr6->addr.s6_addr16[7],
4328 addr6->prefix_len,
4329 card->irq0,result);
4330 sprintf(dbf_text,"sts6%4x",result);
4331 QETH_DBF_TEXT3(0,trace,dbf_text);
4332 }
4333 }
4334 addr6=addr6->if_next;
4335 }
4336#endif
4337
4338 return 0;
4339}
4340
4341static int qeth_is_ipma_in_list(struct qeth_ipm_mac *ipma,
4342 struct qeth_ipm_mac *list)
4343{
4344 while (list) {
4345 if ( (!memcmp(ipma->ip,list->ip,16)) &&
4346 (!memcmp(ipma->mac,list->mac,6)) ) return 1;
4347 list=list->next;
4348 }
4349 return 0;
4350}
4351
4352static void qeth_remove_mc_ifa_from_list(struct qeth_ipm_mac **list,
4353 struct qeth_ipm_mac *ipma)
4354{
4355 struct qeth_ipm_mac *i,*li=NULL;
4356
4357 if ((!(*list)) || (!ipma)) return;
4358
4359 if (*list==ipma) {
4360 *list=ipma->next;
4361 } else {
4362 i=*list;
4363 while (i) {
4364 if (i==ipma) {
4365 li->next=i->next;
4366 } else {
4367 li=i;
4368 }
4369 i=i->next;
4370 }
4371 }
4372}
4373
4374static int qeth_add_mc_ifa_to_list(struct qeth_ipm_mac **list,
4375 struct qeth_ipm_mac *ipma)
4376{
4377 struct qeth_ipm_mac *i;
4378
4379 if (qeth_is_ipma_in_list(ipma,*list))
4380 return -EALREADY;
4381
4382 if (*list==NULL) {
4383 *list=ipma;
4384 } else {
4385 i=*list;
4386 while (i->next) {
4387 i=i->next;
4388 }
4389 i->next=ipma;
4390 }
4391 ipma->next=NULL;
4392 return 0;
4393}
4394
4395static int qeth_setipms(qeth_card_t *card,int use_setipm_retries)
4396{
4397 struct qeth_ipm_mac *addr;
4398 int result;
4399 char dbf_text[15];
4400
4401 sprintf(dbf_text,"stim%4x",card->irq0);
4402 QETH_DBF_TEXT3(0,trace,dbf_text);
4403
4404 if (qeth_is_supported(IPA_MULTICASTING)) {
4405 addr=card->ip_mc_current_state.ipm_ifa;
4406 while (addr) {
4407 if (!qeth_is_ipma_in_list(addr,card->
4408 ip_mc_new_state.ipm_ifa)) {
4409 QETH_DBF_TEXT3(0,trace,"setimdel");
4410 sprintf(dbf_text,"%08x",
4411 *((__u32*)&addr->ip[0]));
4412 QETH_DBF_TEXT3(0,trace,dbf_text);
4413 *((__u32*)(&dbf_text[0]))=
4414 *((__u32*)&addr->mac);
4415 *((__u32*)(&dbf_text[4]))=
4416 *(((__u32*)&addr->mac)+1);
4417 QETH_DBF_HEX3(0,trace,dbf_text,
4418 QETH_DBF_TRACE_LEN);
4419 result=qeth_send_delipm(
4420 card,(__u8*)&addr->ip[0],
4421 (__u8*)addr->mac,4);
4422 if (result) {
4423 PRINT_ERR("was not able to delete " \
4424 "multicast ip %08x/" \
4425 "%02x%02x%02x%02x%02x%02x " \
4426 "on irq x%x " \
4427 "(result: 0x%x), " \
4428 "trying to continue\n",
4429 *((__u32*)&addr->ip[0]),
4430 addr->mac[0],addr->mac[1],
4431 addr->mac[2],addr->mac[3],
4432 addr->mac[4],addr->mac[5],
4433 card->irq0,result);
4434 sprintf(dbf_text,"smdl%4x",result);
4435 QETH_DBF_TEXT3(0,trace,dbf_text);
4436 }
4437 }
4438 addr=addr->next;
4439 }
4440
4441 addr=card->ip_mc_new_state.ipm_ifa;
4442 while (addr) {
4443 if (!qeth_is_ipma_in_list(addr,card->
4444 ip_mc_current_state.
4445 ipm_ifa)) {
4446 QETH_DBF_TEXT3(0,trace,"setimset");
4447 sprintf(dbf_text,"%08x",
4448 *((__u32*)&addr->ip[0]));
4449 QETH_DBF_TEXT3(0,trace,dbf_text);
4450 *((__u32*)(&dbf_text[0]))=
4451 *((__u32*)&addr->mac);
4452 *((__u32*)(&dbf_text[4]))=
4453 *(((__u32*)&addr->mac)+1);
4454 QETH_DBF_HEX3(0,trace,dbf_text,
4455 QETH_DBF_TRACE_LEN);
4456 result=qeth_send_setipm(
4457 card,(__u8*)&addr->ip[0],
4458 (__u8*)addr->mac,4,
4459 use_setipm_retries);
4460 if (result) {
4461 PRINT_ERR("was not able to set " \
4462 "multicast ip %08x/" \
4463 "%02x%02x%02x%02x%02x%02x " \
4464 "on irq x%x " \
4465 "(result: 0x%x), " \
4466 "trying to continue\n",
4467 *((__u32*)&addr->ip[0]),
4468 addr->mac[0],addr->mac[1],
4469 addr->mac[2],addr->mac[3],
4470 addr->mac[4],addr->mac[5],
4471 card->irq0,result);
4472 sprintf(dbf_text,"smst%4x",result);
4473 QETH_DBF_TEXT3(0,trace,dbf_text);
4474 qeth_remove_mc_ifa_from_list(
4475 &card->ip_mc_current_state.
4476 ipm_ifa,addr);
4477 }
4478 }
4479 addr=addr->next;
4480 }
4481
4482#ifdef QETH_IPV6
4483
4484 addr=card->ip_mc_current_state.ipm6_ifa;
4485 while (addr) {
4486 if (!qeth_is_ipma_in_list(addr,card->
4487 ip_mc_new_state.ipm6_ifa)) {
4488 QETH_DBF_TEXT3(0,trace,"setimdl6");
4489 QETH_DBF_HEX3(0,trace,&addr->ip[0],
4490 QETH_DBF_TRACE_LEN);
4491 QETH_DBF_HEX3(0,trace,(&addr->ip[0])+
4492 QETH_DBF_TRACE_LEN,
4493 QETH_DBF_TRACE_LEN);
4494 QETH_DBF_HEX3(0,trace,&addr->mac,
4495 QETH_DBF_TRACE_LEN);
4496 result=qeth_send_delipm(
4497 card,(__u8*)&addr->ip[0],
4498 (__u8*)addr->mac,6);
4499 if (result) {
4500 PRINT_ERR("was not able to delete " \
4501 "multicast ip %04x:%04x:" \
4502 "%04x:%04x:%04x:%04x:" \
4503 "%04x:%04x/" \
4504 "%02x%02x%02x%02x%02x%02x " \
4505 "on irq x%x " \
4506 "(result: 0x%x), " \
4507 "trying to continue\n",
4508 *((__u16*)&addr->ip[0]),
4509 *((__u16*)&addr->ip[2]),
4510 *((__u16*)&addr->ip[4]),
4511 *((__u16*)&addr->ip[6]),
4512 *((__u16*)&addr->ip[8]),
4513 *((__u16*)&addr->ip[10]),
4514 *((__u16*)&addr->ip[12]),
4515 *((__u16*)&addr->ip[14]),
4516 addr->mac[0],addr->mac[1],
4517 addr->mac[2],addr->mac[3],
4518 addr->mac[4],addr->mac[5],
4519 card->irq0,result);
4520 sprintf(dbf_text,"smd6%4x",result);
4521 QETH_DBF_TEXT3(0,trace,dbf_text);
4522 }
4523 }
4524 addr=addr->next;
4525 }
4526
4527 addr=card->ip_mc_new_state.ipm6_ifa;
4528 while (addr) {
4529 if (!qeth_is_ipma_in_list(addr,card->
4530 ip_mc_current_state.
4531 ipm6_ifa)) {
4532 QETH_DBF_TEXT3(0,trace,"setimst6");
4533 QETH_DBF_HEX3(0,trace,&addr->ip[0],
4534 QETH_DBF_TRACE_LEN);
4535 QETH_DBF_HEX3(0,trace,(&addr->ip[0])+
4536 QETH_DBF_TRACE_LEN,
4537 QETH_DBF_TRACE_LEN);
4538 QETH_DBF_HEX3(0,trace,&addr->mac,
4539 QETH_DBF_TRACE_LEN);
4540 result=qeth_send_setipm(
4541 card,(__u8*)&addr->ip[0],
4542 (__u8*)addr->mac,6,
4543 use_setipm_retries);
4544 if (result) {
4545 PRINT_ERR("was not able to set " \
4546 "multicast ip %04x:%04x:" \
4547 "%04x:%04x:%04x:%04x:" \
4548 "%04x:%04x/" \
4549 "%02x%02x%02x%02x%02x%02x " \
4550 "on irq x%x " \
4551 "(result: 0x%x), " \
4552 "trying to continue\n",
4553 *((__u16*)&addr->ip[0]),
4554 *((__u16*)&addr->ip[2]),
4555 *((__u16*)&addr->ip[4]),
4556 *((__u16*)&addr->ip[6]),
4557 *((__u16*)&addr->ip[8]),
4558 *((__u16*)&addr->ip[10]),
4559 *((__u16*)&addr->ip[12]),
4560 *((__u16*)&addr->ip[14]),
4561 addr->mac[0],addr->mac[1],
4562 addr->mac[2],addr->mac[3],
4563 addr->mac[4],addr->mac[5],
4564 card->irq0,result);
4565 sprintf(dbf_text,"sms6%4x",result);
4566 QETH_DBF_TEXT3(0,trace,dbf_text);
4567 qeth_remove_mc_ifa_from_list(
4568 &card->ip_mc_current_state.
4569 ipm6_ifa,addr);
4570 }
4571 }
4572 addr=addr->next;
4573 }
4574#endif
4575 return 0;
4576 } else return 0;
4577}
4578
4579static void qeth_clone_ifa(struct in_ifaddr *src,struct in_ifaddr *dest)
4580{
4581 memcpy(dest,src,sizeof(struct in_ifaddr));
4582 dest->ifa_next=NULL;
4583}
4584
4585#ifdef QETH_IPV6
4586static void qeth_clone_ifa6(struct inet6_ifaddr *src,
4587 struct inet6_ifaddr *dest)
4588{
4589 memcpy(dest,src,sizeof(struct inet6_ifaddr));
4590 dest->if_next=NULL;
4591}
4592#endif
4593
4594
4595
4596#define QETH_STANDARD_RETVALS \
4597 ret_val=-EIO; \
4598 if (result==IPA_REPLY_SUCCESS) ret_val=0; \
4599 if (result==-EFAULT) ret_val=-EFAULT; \
4600 if (result==IPA_REPLY_FAILED) ret_val=-EIO; \
4601 if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP
4602
4603static int qeth_do_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
4604{
4605 char *data;
4606 int result,i,ret_val;
4607 int version=4;
4608 qeth_card_t *card;
4609 char dbf_text[15];
4610 char buff[100];
4611
4612 card=(qeth_card_t*)dev->priv;
4613
4614 sprintf(dbf_text,"ioct%4x",card->irq0);
4615 QETH_DBF_TEXT2(0,trace,dbf_text);
4616 sprintf(dbf_text,"cmd=%4x",cmd);
4617 QETH_DBF_TEXT2(0,trace,dbf_text);
4618 QETH_DBF_HEX2(0,trace,&rq,sizeof(void*));
4619
4620 if ((cmd<SIOCDEVPRIVATE) || (cmd>SIOCDEVPRIVATE+5))
4621 return -EOPNOTSUPP;
4622 if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff)))
4623 return -EFAULT;
4624 data=buff;
4625
4626 if ((cmd<SIOCDEVPRIVATE) || (cmd>SIOCDEVPRIVATE+5))
4627 return -EOPNOTSUPP;
4628 if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff)))
4629 return -EFAULT;
4630 data=buff;
4631
4632 if ( (!atomic_read(&card->is_registered))||
4633 (!atomic_read(&card->is_hardsetup))||
4634 (atomic_read(&card->is_gone)) ) return -ENODEV;
4635
4636 if (atomic_read(&card->shutdown_phase)) return -ENODEV;
4637
4638 if (down_interruptible ( &card->ioctl_sem ) )
4639 return -ERESTARTSYS;
4640
4641 if (atomic_read(&card->shutdown_phase)) {
4642 ret_val=-ENODEV;
4643 goto out;
4644 }
4645
4646 if ( (!atomic_read(&card->is_registered))||
4647 (!atomic_read(&card->is_hardsetup))||
4648 (atomic_read(&card->is_gone)) ) {
4649 ret_val=-ENODEV;
4650 goto out;
4651 }
4652
4653 switch (cmd) {
4654 case SIOCDEVPRIVATE+0:
4655 if (!capable(CAP_NET_ADMIN)) {
4656 ret_val=-EPERM;
4657 break;
4658 }
4659 result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING,
4660 IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
4661 rq->ifr_ifru.ifru_ivalue,4);
4662 QETH_STANDARD_RETVALS;
4663 if (result==3) ret_val=-EINVAL;
4664 break;
4665 case SIOCDEVPRIVATE+1:
4666 if (!capable(CAP_NET_ADMIN)) {
4667 ret_val=-EPERM;
4668 break;
4669 }
4670 result = qeth_queryarp(card,rq,version,IPA_ARP_PROCESSING,
4671 IPA_CMD_ASS_ARP_QUERY_INFO,data,4);
4672
4673 QETH_STANDARD_RETVALS;
4674 break;
4675 case SIOCDEVPRIVATE+2:
4676 if (!capable(CAP_NET_ADMIN)) {
4677 ret_val=-EPERM;
4678 break;
4679 }
4680 for (i=12;i<24;i++) if (data[i]) version=6;
4681 result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING,
4682 IPA_CMD_ASS_ARP_ADD_ENTRY,
4683 (long)data,56);
4684 QETH_STANDARD_RETVALS;
4685 break;
4686 case SIOCDEVPRIVATE+3:
4687 if (!capable(CAP_NET_ADMIN)) {
4688 ret_val=-EPERM;
4689 break;
4690 }
4691 for (i=12;i<24;i++) if (data[i]) version=6;
4692 result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING,
4693 IPA_CMD_ASS_ARP_REMOVE_ENTRY,
4694 (long)data,16);
4695 QETH_STANDARD_RETVALS;
4696 break;
4697 case SIOCDEVPRIVATE+4:
4698 if (!capable(CAP_NET_ADMIN)) {
4699 ret_val=-EPERM;
4700 break;
4701 }
4702 result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING,
4703 IPA_CMD_ASS_ARP_FLUSH_CACHE,
4704 0,0);
4705 QETH_STANDARD_RETVALS;
4706 break;
4707 case SIOCDEVPRIVATE+5:
4708 result=qeth_send_snmp_control(card,rq,
4709 IPA_CMD_SETADAPTERPARMS,
4710 IPA_SETADP_SET_SNMP_CONTROL,
4711 data,4);
4712 QETH_STANDARD_RETVALS;
4713 break;
4714 case SIOCDEVPRIVATE+6:
4715 if (!card->is_guest_lan &&
4716 (card->type == QETH_CARD_TYPE_OSAE))
4717 ret_val = 1;
4718 else
4719 ret_val = 0;
4720 break;
4721
4722 default:
4723 ret_val=-EOPNOTSUPP;
4724 goto out;
4725 }
4726out:
4727 up (&card->ioctl_sem);
4728
4729 sprintf(dbf_text,"ret=%4x",ret_val);
4730 QETH_DBF_TEXT2(0,trace,dbf_text);
4731
4732 return ret_val;
4733}
4734
4735static void qeth_clear_ifamc_list(struct qeth_ipm_mac **ifa_list)
4736{
4737 struct qeth_ipm_mac *ifa;
4738 while (*ifa_list) {
4739 ifa=*ifa_list;
4740 *ifa_list=ifa->next;
4741 kfree(ifa);
4742 }
4743}
4744
4745#ifdef QETH_IPV6
4746static void qeth_clear_ifa6_list(struct inet6_ifaddr **ifa_list)
4747{
4748 struct inet6_ifaddr *ifa;
4749 while (*ifa_list) {
4750 ifa=*ifa_list;
4751 *ifa_list=ifa->if_next;
4752 kfree(ifa);
4753 }
4754}
4755
4756static void qeth_takeover_ip_ipms6(qeth_card_t *card)
4757{
4758 struct inet6_ifaddr *ifa,*ifanew;
4759 char dbf_text[15];
4760 int remove;
4761#ifdef QETH_VLAN
4762 struct vlan_group *card_group;
4763 int i;
4764#endif
4765
4766 struct qeth_ipm_mac *ipmanew;
4767 struct ifmcaddr6 *im6;
4768 struct inet6_dev *in6_dev;
4769#ifdef QETH_VLAN
4770 struct inet6_dev *in6_vdev;
4771#endif
4772 char buf[MAX_ADDR_LEN];
4773
4774 sprintf(dbf_text,"tip6%4x",card->irq0);
4775 QETH_DBF_TEXT3(0,trace,dbf_text);
4776
4777
4778 qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa);
4779
4780 card->ip_current_state.ip6_ifa=card->ip_new_state.ip6_ifa;
4781 card->ip_new_state.ip6_ifa=NULL;
4782
4783
4784
4785 qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa);
4786
4787 card->ip_mc_current_state.ipm6_ifa=card->ip_mc_new_state.ipm6_ifa;
4788
4789
4790 card->ip_mc_new_state.ipm6_ifa=NULL;
4791
4792 if((in6_dev=in6_dev_get(card->dev))==NULL) {
4793 sprintf(dbf_text,"id16%4x",card->irq0);
4794 QETH_DBF_TEXT2(0,trace,dbf_text);
4795 goto out;
4796 }
4797 read_lock(&in6_dev->lock);
4798
4799
4800
4801 QETH_DBF_TEXT4(0,trace,"to-ip6s");
4802 if ( (atomic_read(&card->is_open)) && (card->dev->ip6_ptr) &&
4803 (((struct inet6_dev*)card->dev->ip6_ptr)->addr_list) ) {
4804 ifa=((struct inet6_dev*)card->dev->ip6_ptr)->addr_list;
4805
4806 while (ifa) {
4807 ifanew=kmalloc(sizeof(struct inet6_ifaddr),GFP_KERNEL);
4808 if (!ifanew) {
4809 PRINT_WARN("No memory for IP address " \
4810 "handling. Some of the IPs " \
4811 "will not be set on %s.\n",
4812 card->dev_name);
4813 QETH_DBF_TEXT2(0,trace,"TOIPNMEM");
4814 } else {
4815 qeth_clone_ifa6(ifa,ifanew);
4816 remove=qeth_add_ifa6_to_list(
4817 &card->ip_new_state.ip6_ifa,ifanew);
4818 QETH_DBF_HEX4(0,trace,&ifanew->addr.s6_addr,
4819 QETH_DBF_TRACE_LEN);
4820 QETH_DBF_HEX4(0,trace,&ifanew->addr.s6_addr+
4821 QETH_DBF_TRACE_LEN,
4822 QETH_DBF_TRACE_LEN);
4823 sprintf(dbf_text,"pref%4u",ifanew->prefix_len);
4824 QETH_DBF_TEXT4(0,trace,dbf_text);
4825 if (remove) {
4826 kfree(ifanew);
4827 QETH_DBF_TEXT4(0,trace,"alrdy6rm");
4828 }
4829 }
4830 ifa=ifa->if_next;
4831 }
4832 }
4833#ifdef QETH_VLAN
4834
4835
4836
4837 QETH_DBF_TEXT4(0,trace,"to-vip6s");
4838 if ( (qeth_is_supported(IPA_FULL_VLAN)) &&
4839 (atomic_read(&card->is_open)) ) {
4840 card_group = (struct vlan_group *) card->vlangrp;
4841 if (card_group) for (i=0;i<VLAN_GROUP_ARRAY_LEN;i++) {
4842 if ( (card_group->vlan_devices[i]) &&
4843 (card_group->vlan_devices[i]->flags&IFF_UP)&&
4844 ((struct inet6_dev *) card_group->
4845 vlan_devices[i]->ip6_ptr) ) {
4846 ifa=((struct inet6_dev *)
4847 card_group->vlan_devices[i]->ip6_ptr)->
4848 addr_list;
4849
4850 while (ifa) {
4851 ifanew=kmalloc(sizeof(struct inet6_ifaddr),GFP_KERNEL);
4852 if (!ifanew) {
4853 PRINT_WARN("No memory for IP address " \
4854 "handling. Some of the IPs " \
4855 "will not be set on %s.\n",
4856 card->dev_name);
4857 QETH_DBF_TEXT2(0,trace,"TOIPNMEM");
4858 } else {
4859 qeth_clone_ifa6(ifa,ifanew);
4860 remove=qeth_add_ifa6_to_list
4861 (&card->ip_new_state.ip6_ifa,ifanew);
4862 QETH_DBF_HEX4(0,trace,&ifanew->addr.s6_addr,
4863 QETH_DBF_TRACE_LEN);
4864 QETH_DBF_HEX4(0,trace,&ifanew->addr.s6_addr+
4865 QETH_DBF_TRACE_LEN,
4866 QETH_DBF_TRACE_LEN);
4867 sprintf(dbf_text,"pref%4u",ifanew->prefix_len);
4868 QETH_DBF_TEXT4(0,trace,dbf_text);
4869 if (remove) {
4870 kfree(ifanew);
4871 QETH_DBF_TEXT4(0,trace,"alrdv6rm");
4872 }
4873 }
4874 ifa=ifa->if_next;
4875 }
4876 }
4877 }
4878 }
4879#endif
4880
4881 QETH_DBF_TEXT4(0,trace,"to-ipm6s");
4882 if (atomic_read(&card->is_open))
4883 for (im6=in6_dev->mc_list;im6;im6=im6->next) {
4884 ndisc_mc_map(&im6->mca_addr,buf,card->dev,0);
4885 ipmanew=(struct qeth_ipm_mac*)kmalloc(
4886 sizeof(struct qeth_ipm_mac),GFP_KERNEL);
4887 if (!ipmanew) {
4888 PRINT_WARN("No memory for IPM address " \
4889 "handling. Multicast IP " \
4890 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" \
4891 "will not be set on %s.\n",
4892 im6->mca_addr.s6_addr16[0],
4893 im6->mca_addr.s6_addr16[1],
4894 im6->mca_addr.s6_addr16[2],
4895 im6->mca_addr.s6_addr16[3],
4896 im6->mca_addr.s6_addr16[4],
4897 im6->mca_addr.s6_addr16[5],
4898 im6->mca_addr.s6_addr16[6],
4899 im6->mca_addr.s6_addr16[7],
4900 card->dev_name);
4901 QETH_DBF_TEXT2(0,trace,"TOIPMNMM");
4902 } else {
4903 memset(ipmanew,0,sizeof(struct qeth_ipm_mac));
4904 memcpy(ipmanew->mac,buf,OSA_ADDR_LEN);
4905 memcpy(ipmanew->ip,im6->mca_addr.s6_addr,16);
4906 ipmanew->next=NULL;
4907 remove=qeth_add_mc_ifa_to_list(
4908 &card->ip_mc_new_state.ipm6_ifa,ipmanew);
4909 QETH_DBF_HEX4(0,trace,&ipmanew->ip,
4910 QETH_DBF_TRACE_LEN);
4911 QETH_DBF_HEX4(0,trace,&ipmanew->ip+
4912 QETH_DBF_TRACE_LEN,
4913