linux-old/drivers/s390/net/qeth.c
<<
>>
Prefs
   1/*
   2 *
   3 * linux/drivers/s390/net/qeth.c ($Revision: 1.337.4.24 $)
   4 *
   5 * Linux on zSeries OSA Express and HiperSockets support
   6 *
   7 * Copyright 2000,2003 IBM Corporation
   8 *
   9 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  10 *            Cornelia Huck <cohuck@de.ibm.com> (chandev stuff,
  11 *                                               numerous bugfixes)
  12 *            Frank Pavlic <pavlic@de.ibm.com>  (query/purge ARP, SNMP, fixes)
  13 *            Andreas Herrmann <aherrman@de.ibm.com> (bugfixes)
  14 *
  15 * This program is free software; you can redistribute it and/or modify
  16 * it under the terms of the GNU General Public License as published by
  17 * the Free Software Foundation; either version 2, or (at your option)
  18 * any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28 */
  29
  30/*
  31 * For all devices, three channels must be available to the driver. One
  32 * channel is the read channel, one is the write channel and the third
  33 * one is the channel used to control QDIO.
  34 *
  35 * There are several stages from the channel recognition to the running
  36 * network device:
  37 * - The channels are scanned and ordered due to the parameters (see
  38 *   MODULE_PARM_DESC)
  39 * - The card is hardsetup: this means, that the communication channels
  40 *   are prepared
  41 * - The card is softsetup: this means, that commands are issued
  42 *   to activate the network parameters
  43 * - After that, data can flow through the card (transported by QDIO)
  44 *
  45 *IPA Takeover:
  46 * /proc/qeth_ipa_takeover provides the possibility to add and remove
  47 * certain ranges of IP addresses to the driver. As soon as these
  48 * addresses have to be set by the driver, the driver uses the OSA
  49 * Address Takeover mechanism.
  50 * reading out of the proc-file displays the registered addresses;
  51 * writing into it changes the information. Only one command at one
  52 * time must be written into the file. Subsequent commands are ignored.
  53 * The following commands are available:
  54 * inv4
  55 * inv6
  56 * add4 <ADDR>/<mask bits>[:<interface>]
  57 * add6 <ADDR>/<mask bits>[:<interface>]
  58 * del4 <ADDR>/<mask bits>[:<interface>]
  59 * del6 <ADDR>/<mask bits>[:<interface>]
  60 * inv4 and inv6 toggle the IPA takeover behaviour for all interfaces:
  61 * when inv4 was input once, all addresses specified with add4 are not
  62 * set using the takeover mechanism, but all other IPv4 addresses are set so.
  63 *
  64 * add# adds an address range, del# deletes an address range. # corresponds
  65 * to the IP version (4 or 6).
  66 * <ADDR> is a 8 or 32byte hexadecimal view of the IP address.
  67 * <mask bits> specifies the number of bits which are set in the network mask.
  68 * <interface> is optional and specifies the interface name to which the
  69 * address range is bound.
  70 * E. g.
  71 *   add4 C0a80100/24
  72 * activates all addresses in the 192.168.10 subnet for address takeover.
  73 * Note, that the address is not taken over before an according ifconfig
  74 * is executed.
  75 *
  76 *VIPA:
  77 * add_vipa4 <ADDR>:<interface>
  78 * add_vipa6 <ADDR>:<interface>
  79 * del_vipa4 <ADDR>:<interface>
  80 * del_vipa6 <ADDR>:<interface>
  81 *
  82 * the specified address is set/unset as VIPA on the specified interface.
  83 * use the src_vipa package to exploit this out of arbitrary applications.
  84 *
  85 *Proxy ARP:
  86 *
  87 * add_rxip4 <ADDR>:<interface>
  88 * add_rxip6 <ADDR>:<interface>
  89 * del_rxip4 <ADDR>:<interface>
  90 * del_rxip6 <ADDR>:<interface>
  91 *
  92 * the specified address is set/unset as "do not fail a gratuitous ARP"
  93 * on the specified interface. this can be used to act as a proxy ARP.
  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 /* CONFIG_CHANDEV */
 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 /* CONFIG_PROC_FS */
 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/****************** MODULE PARAMETER VARIABLES ********************/
 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/****************** MODULE STUFF **********************************/
 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/******************** HERE WE GO ***********************************/
 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 /* QETH_PERFORMANCE_STATS */
 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/* thought I could get along without forward declarations...
 221 * just lazyness here */
 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/* not a macro, as one of the arguments is atomic_read */
 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 * This is our local skb_unshare, only with pskb_copy instead of skb_copy.
 247 * We place our headers whare Ethernet MAC was, so we do not need
 248 * full skb_copy.
 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); /* free our shared copy */
 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); /* time>>12 is microseconds, we divide it
 266                                    by 1024 */
 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 /* QETH_PERFORMANCE_STATS */
 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 /* QETH_DBF_LIKE_HELL */
 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 /* QETH_DBF_LIKE_HELL */
 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 /* CONFIG_ARCH_S390X */
 418#define QETH_GET_ADDR(x) ((__u32)x)
 419#endif /* CONFIG_ARCH_S390X */
 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                clear_bit(__LINK_STATE_DOWN,&dev->flags);
 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                set_bit(__LINK_STATE_DOWN,&dev->flags);
 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                if (card->saved_dev_flags&__LINK_STATE_DOWN)
 682                        set_bit(__LINK_STATE_DOWN,&card->dev->flags);
 683                else
 684                        clear_bit(__LINK_STATE_DOWN,&card->dev->flags);
 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                card->saved_dev_flags=card->dev->flags&__LINK_STATE_DOWN;
 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        /* ok, we've to try it somehow else */
 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                /* tr multicast? */
 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                /* eth or so multicast? */
 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 ********************
 827TODO: IPv6!!!
 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                        /* we don't do a  netif_stop_queue(card->dev);
 935                           we better discard all packets --
 936                           the outage could take longer */
 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                /* we checked for buffer!=0 in IS_IPA */
 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        /* no probs */
 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        /* set up next read ccw */
1001        memcpy(&card->dma_stuff->read_ccw,READ_CCW,sizeof(ccw1_t));
1002        card->dma_stuff->read_ccw.count=QETH_BUFSIZE;
1003        /* recbuf is not yet used by read channel program */
1004        card->dma_stuff->read_ccw.cda=QETH_GET_ADDR(card->dma_stuff->recbuf);
1005
1006        /* we don't s390irq_spin_lock_irqsave(card->irq0,flags), as
1007           we are only called in the interrupt handler */
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 /* QETH_DBF_LIKE_HELL */
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                        /* we assume here, that ptr&(PAGE_SIZE-1)==0 */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_DBF_LIKE_HELL */
1200                        return;
1201                }
1202                requeue_counter=atomic_read(&card->requeue_counter);
1203                pos=atomic_read(&card->requeue_position);
1204
1205                start=pos;
1206                /* omit the situation with 128 simultaneously
1207                   enqueued buffers, as then we can't benefit from PCI
1208                   avoidance anymore -- therefore we let count not grow as
1209                   big as requeue_counter */
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                /* stop points to the position after the last element */
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 /* QETH_DBF_LIKE_HELL */
1249                if (wrapped) {
1250                        cnt1=QDIO_MAX_BUFFERS_PER_Q-start;
1251                        cnt2=stop;
1252                } else {
1253                        cnt1=count;
1254                        /* cnt2 is already set to 0 */
1255                }
1256
1257                atomic_sub(count,&card->requeue_counter);
1258                /* this is the only place where card->requeue_position is
1259                   written to, so that's ok (as it is in a lock) */
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 /* QETH_VLAN */
1322        skb=dev_alloc_skb(len);
1323#endif /* QETH_VLAN */
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        /* header fits in current element? */
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 /* QETH_DBF_LIKE_HELL */
1385                        return NULL; /* no more data in buffer */
1386                }
1387                /* set hdr to next element */
1388                element++;
1389                pos_in_el=0;
1390                curr_len=SBALE_LEN(element);
1391                /* does it fit in there? */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_DBF_LIKE_HELL */
1410
1411        pos_in_el+=QETH_HEADER_SIZE;
1412        if (curr_len<=pos_in_el) {
1413                /* switch to next element for data */
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 /* QETH_DBF_LIKE_HELL */
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                        /* we don't need to calculate curr_len */
1486                        pos_in_el=0;
1487#else /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */
1488                        pos_in_el+=step;
1489#endif /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */
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 /* QETH_DBF_LIKE_HELL */
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        /* inform about errors */
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 /* QETH_PERFORMANCE_STATS */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_PERFORMANCE_STATS */
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 /* QETH_IPV6 */
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 /* QETH_IPV6 */
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                                /* clear source MAC for security reasons */
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                        /* do we have a checksummed packet? */
1698
1699                        /* we only check for TCP/UDP checksums when the
1700                         * pseudo header was also checked sucessfully -- for
1701                         * the rest of the packets, it's not clear, whether
1702                         * the upper layer csum is alright. And they
1703                         * shouldn't occur too often anyway in real life */
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                                /* csum does not need to be set
1710                                 * inbound anyway
1711                                 *
1712                                 * vlan is not an issue here, it's still in
1713                                 * the QDIO header, not pushed in the
1714                                 * skb yet *
1715                                int ip_len=(skb->data[0]&0x0f)<<2;
1716
1717                                if (*(__u8*)(hdr_ptr+11)&
1718                                    QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE) {
1719                                        * get the UDP checksum *
1720                                        skb->csum=*(__u16*)
1721                                                (&skb->data[ip_len+
1722                                                 QETH_UDP_CSUM_OFFSET]);
1723                                } else {
1724                                        * get the TCP checksum *
1725                                        skb->csum=*(__u16*)
1726                                                (&skb->data[ip_len+
1727                                                 QETH_TCP_CSUM_OFFSET]);
1728                                }
1729                                 */
1730                                skb->ip_summed=CHECKSUM_UNNECESSARY;
1731                        } else {
1732                                /* make the stack check it */
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                                         if (*(__u8*)(hdr_ptr+11) & 
1746                                             QETH_EXT_HEADER_INCLUDE_VLAN_TAG) {
1747                                           *vlan_tag = *(__u16*)(hdr_ptr+28);
1748                                           *(vlan_tag+1)= *(__u16*)(hdr_ptr+30);
1749                                         } else {
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 /* QETH_PERFORMANCE_STATS */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_DBF_LIKE_HELL */
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        /* before we're going to overwrite 
1805         * this location with next hop ip.
1806         * v6 uses passthrough, v4 sets the tag in the QDIO header */
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; /* as skb->len includes
1821                                                  the header now */
1822
1823        /* yes, I know this is doubled code, but a small little bit
1824           faster maybe */
1825        if (version==4) { /* IPv4 */
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                        /* fill in destination address used
1841                         * in ip header */
1842                        *((__u32*)(&hdr->dest_addr[12]))=
1843                                skb->nh.iph->daddr;
1844                }
1845        } else if (version==6) { /* IPv6 or passthru */
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 { /* default: RTN_UNICAST */
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                        /* fill in destination address used
1869                         * in ip header */
1870                        memcpy(hdr->dest_addr,
1871                               &skb->nh.ipv6h->daddr,16);
1872                }
1873        } else { /* passthrough */
1874                if (!memcmp(skb->data+QETH_HEADER_SIZE,
1875                            skb->dev->broadcast,6)) { /* broadcast? */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_DBF_LIKE_HELL */
1908        int first_element=element;
1909
1910        while (length>0) {
1911                /* length_here is the remaining amount of data in this page */
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 /* QETH_DBF_LIKE_HELL */
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        /* can happen, when in the time between deciding to pack and sending
1967           the next packet the lower mark was reached: */
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 /* QETH_PERFORMANCE_STATS */
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        /* we can override that, as we have at most 127 buffers enqueued */
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 /* QETH_DBF_LIKE_HELL */
2010
2011        /* we always set the outbound pci flag, don't care, whether the
2012         * adapter honors it or not */
2013        switch (card->send_state[queue]) {
2014        case SEND_STATE_DONT_PACK:
2015                /* only request a PCI, if the fill level of the queue
2016                 * is close to the high watermark, so that we don't
2017                 * loose initiative during packing */
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                /* compensate queues that wrapped around */
2023                if (position_for_do_qdio<last_pci)
2024                        last_pci-=QDIO_MAX_BUFFERS_PER_Q;
2025
2026                /* reduce the number of PCIs in cases where we are always
2027                 * a little below the high watermark for packing -- request
2028                 * PCIs less frequently */
2029                if (position_for_do_qdio-last_pci<
2030                    HIGH_WATERMARK_PACK-WATERMARK_FUZZ) break;
2031
2032                /* set the PCI bit */
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                /* so:
2042                 * last_pci is the position of the last pci we've set
2043                 * position_for_do_qdio is the position we will send out now
2044                 * outbound_used_buffers is the number of buffers used (means
2045                 *   all buffers OSA has, inclusive position_for_do_qdio)
2046                 *
2047                 * we have to request a pci, if we have got the buffer of the
2048                 * last_pci position back.
2049                 *
2050                 * position_for_do_qdio-outbound_used_buffers is the newest
2051                 *   buffer that we got back from OSA
2052                 *
2053                 * if this is greater or equal than the last_pci position,
2054                 * we should request a pci, as no pci request is
2055                 * outstanding anymore
2056                 */
2057                if (position_for_do_qdio-
2058                    atomic_read(&card->outbound_used_buffers[queue])>=
2059                    last_pci) {
2060                        /* set the PCI bit */
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        /* this has to be at the end, otherwise a buffer could be flushed
2073           twice (see coment in qeth_do_send_packet) */
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                /* look at qdio_error and sbalf 15 */
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; /* should never happen */
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: /* fallthrough */
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 /* QETH_DBF_LIKE_HELL */
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                        /* analyze, how many retries we did so far */
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                        /* else error stays RETRY for the switch statemnet */
2191                } else if (error==ERROR_LINK_FAILURE) {
2192                        /* we don't want to log failures resulting from
2193                         * too many retries */
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                                /* retry packet async (quickly) ... */
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 /* QETH_DBF_LIKE_HELL */
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        /* Move the mac addresses to the beginning of the new header.
2283         * We are using three memcpys instead of one memmove to save
2284         * cycles.
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        /*first two bytes  = ETH_P_8021Q (0x8100)
2298         *second two bytes = VLANID
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        /* sanity check, the Linux memory allocation scheme should
2365           never present us cases like this one (the 32bytes header plus
2366           the first 40 bytes of the paket cross a 4k boundary) */
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        /* we need to write to next_element_to_fill as
2391           qeth_flush_packed_packets checks it */
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 /* QETH_PERFORMANCE_STATS */
2401
2402        qeth_flush_packed_packets(card,queue,0);
2403}
2404
2405/* no checks, if all elements are used, as then we would not be here (at most
2406   127 buffers are enqueued) */
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        /* sanity check, dev->hard_header_len should prevent this */
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        /* sanity check, the Linux memory allocation scheme should
2467           never present us cases like this one (the 32bytes header plus
2468           the first 40 bytes of the paket cross a 4k boundary) */
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 /* QETH_PERFORMANCE_STATS */
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 /* QETH_DBF_LIKE_HELL */
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        /* we are not called under int, so we just spin */
2617        /* happens around once a second under heavy traffic. takes a little
2618         * bit less than 10usec in avg. on a z900 */
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 /* QETH_PERFORMANCE_STATS */
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 /* QETH_PERFORMANCE_STATS */
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        /* ATOMIC: (NORMAL->UNLOCKED, FLUSH->NORMAL) */
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 /* QETH_PERFORMANCE_STATS */
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 /* CONFIG_ARCH_S390X */
2702        asm volatile ("lr %0,15" : "=d" (stackptr));
2703#endif /* CONFIG_ARCH_S390X */
2704        /* prevent stack overflows */
2705        /* normal and async stack is both 8k on s390 and 16k on s390x,
2706         * so it doesn't matter whether we're in an interrupt */
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 /* QETH_DBF_LIKE_HELL */
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 /* QETH_PERFORMANCE_STATS */
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                 * in theory, if we run in undef-ed QETH_IPV6, we should
2749                 * always unshare, because we do skb_push, then overwrite
2750                 * that place with OSA header in qeth_send_packet_fast().
2751                 * But it is only visible to one application - tcpdump.
2752                 * Nobody else cares if (fake) MAC header gets smashed.
2753                 * So, we only do it if fake_ll is in effect.
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 * This function is needed to tell af_packet.c to process headers.
2773 * It is not called from there, but only from the transmit path,
2774 * when we do not need any actual header.
2775 *
2776 * N.B. Why do we insist on kludging here instead of fixing tcpdump?
2777 * Because tcpdump is shared among gazillions of platforms, and
2778 * there is a) no reliable way to identify qeth or its packets
2779 * in pcap-linux.c (sll->sll_halen is the only hope); b) no easy
2780 * way to pass this information from libpcap to tcpdump proper.
2781 *
2782 * XXX This fails with TR: traffic flows ok, but tcpdump remains confused.
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        /* XXX Maybe dev->hard_header_len here? Then skb_pull by same size. */
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,&current_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        /* we've got to check once again to close the window */
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,&current_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,&current_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        /* we've got to check once again to close the window */
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,&current_wait_q);
2950        
2951        return retval;
2952}
2953
2954static void qeth_snmp_notify(void)
2955{
2956        /*notify all  registered processes */
2957        struct list_head *l;
2958        struct qeth_notify_list *n_entry;
2959
2960        QETH_DBF_TEXT5(0,trace,"snmpnoti");
2961        spin_lock(&notify_lock);
2962        list_for_each(l, &notify_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(&notify_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        /* we lock very early to synchronize access to seqnos */
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        /* there is noone doing this except sleep and this function */
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                /* re-enable qeth_send_control_data again */
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                        /* re-enable qeth_send_control_data again */
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                        /* re-enable qeth_send_control_data again */
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        /* don't muck around with ipv6 if there's no use to do so */
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 /* QETH_SEND_STOPLAN_ON_SHUTDOWN */
3197        return 0;
3198#endif /* QETH_SEND_STOPLAN_ON_SHUTDOWN */
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        /* don't muck around with ipv6 if there's no use to do so */
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                /* adjust sizes for big requests */
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                       /* limit here to a page or so */
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; /* ne stands for new entry,
3956                                              le is last entry */
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                        /* we don't want to hold the lock for a long time...
3972                         * so we clone the entry */
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                        /* we don't want to hold the lock for a long time...
4004                         * so we clone the entry */
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        /* strip off RESET_ROUTING_FLAG */
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 /* QETH_IPV6 */
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 /* QETH_IPV6 */
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        /* here we go with IPv6 */
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 /* QETH_IPV6 */
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                /* here we go with IPv6 */
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 /* QETH_IPV6 */
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 /* QETH_IPV6 */
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        /* unicast */
4777        /* clear ip_current_state */
4778        qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa);
4779        /* take it over */
4780        card->ip_current_state.ip6_ifa=card->ip_new_state.ip6_ifa;
4781        card->ip_new_state.ip6_ifa=NULL;
4782
4783        /* multicast */
4784        /* clear ip_mc_current_state */
4785        qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa);
4786        /* take it over */
4787        card->ip_mc_current_state.ipm6_ifa=card->ip_mc_new_state.ipm6_ifa;
4788        /* get new one, we try to have the same order as ifa_list in device
4789           structure, for what reason ever*/
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        /* get new one, we try to have the same order as ifa_list in device
4800           structure, for what reason ever*/
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/*append all known VLAN IP Addresses corresponding 
4835  to the real device card->dev->ifindex 
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