Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Wed, 23 Sep 2009 23:23:46 +0000 (16:23 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Sep 2009 23:23:46 +0000 (16:23 -0700)
Conflicts:
drivers/net/wireless/iwlwifi/iwl-rx.c

158 files changed:
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/include/mach/board.h
drivers/atm/he.c
drivers/atm/solos-attrlist.c
drivers/atm/solos-pci.c
drivers/net/8139cp.c
drivers/net/Kconfig
drivers/net/atl1c/atl1c_main.c
drivers/net/atl1e/atl1e.h
drivers/net/atl1e/atl1e_main.c
drivers/net/b44.c
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_main.c
drivers/net/bonding/bond_main.c
drivers/net/can/Kconfig
drivers/net/can/Makefile
drivers/net/can/usb/Makefile [new file with mode: 0644]
drivers/net/can/usb/ems_usb.c [new file with mode: 0644]
drivers/net/can/vcan.c
drivers/net/cnic.c
drivers/net/cpmac.c
drivers/net/ehea/ehea_main.c
drivers/net/igb/e1000_82575.c
drivers/net/igb/e1000_82575.h
drivers/net/igb/e1000_defines.h
drivers/net/igb/e1000_mac.c
drivers/net/igb/e1000_mac.h
drivers/net/igb/e1000_phy.c
drivers/net/igb/igb_main.c
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_82598.c
drivers/net/ixgbe/ixgbe_82599.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/mlx4/catas.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pppol2tp.c
drivers/net/sky2.c
drivers/net/smc91x.h
drivers/net/sunvnet.c
drivers/net/tun.c
drivers/net/usb/cdc-phonet.c
drivers/net/usb/kaweth.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/wl12xx/wl1271_main.c
drivers/net/xilinx_emaclite.c
drivers/serial/serial_cs.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/cpc-usb/Kconfig [deleted file]
drivers/staging/cpc-usb/Makefile [deleted file]
drivers/staging/cpc-usb/TODO [deleted file]
drivers/staging/cpc-usb/cpc-usb_drv.c [deleted file]
drivers/staging/cpc-usb/cpc.h [deleted file]
drivers/staging/cpc-usb/cpc_int.h [deleted file]
drivers/staging/cpc-usb/cpcusb.h [deleted file]
drivers/staging/cpc-usb/sja2m16c.h [deleted file]
drivers/staging/cpc-usb/sja2m16c_2.c [deleted file]
firmware/Makefile
firmware/WHENCE
firmware/cis/MT5634ZLX.cis.ihex [new file with mode: 0644]
firmware/cis/PCMLM28.cis.ihex [new file with mode: 0644]
firmware/cis/RS-COM-2P.cis.ihex [new file with mode: 0644]
include/keys/rxrpc-type.h
include/linux/igmp.h
include/linux/net.h
include/linux/netdevice.h
include/linux/netlink.h
include/linux/notifier.h
include/linux/rxrpc.h
include/linux/usb/usbnet.h
include/net/addrconf.h
include/net/protocol.h
include/net/sch_generic.h
include/net/tcp.h
kernel/sys_ni.c
lib/vsprintf.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/can/af_can.c
net/core/dev.c
net/dccp/ccids/Kconfig
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid2.h
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/ccids/lib/loss_interval.c
net/dccp/ccids/lib/loss_interval.h
net/dccp/ccids/lib/packet_history.c
net/dccp/ccids/lib/packet_history.h
net/dccp/ccids/lib/tfrc.h
net/dccp/ccids/lib/tfrc_equation.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ieee802154/dgram.c
net/ieee802154/netlink.c
net/ieee802154/raw.c
net/ipv4/af_inet.c
net/ipv4/ah4.c
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ipcomp.c
net/ipv4/ipmr.c
net/ipv4/protocol.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tunnel4.c
net/ipv4/udplite.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/ip6_input.c
net/ipv6/ip6mr.c
net/ipv6/ipcomp6.c
net/ipv6/mcast.c
net/ipv6/protocol.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/tunnel6.c
net/ipv6/udp.c
net/ipv6/udplite.c
net/iucv/af_iucv.c
net/iucv/iucv.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/phonet/pn_dev.c
net/rds/af_rds.c
net/rose/af_rose.c
net/rxrpc/ar-ack.c
net/rxrpc/ar-internal.h
net/rxrpc/ar-key.c
net/rxrpc/ar-security.c
net/rxrpc/rxkad.c
net/sched/sch_api.c
net/sched/sch_drr.c
net/sched/sch_mq.c
net/sched/sch_multiq.c
net/sched/sch_prio.c
net/sctp/ipv6.c
net/sctp/protocol.c
net/socket.c

index b7f23324231560635b0d053ac7fac703a249e19f..6026c2e0d5ccb791addf06de45882dd355b86a9e 100644 (file)
@@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct atmel_ac97_data *data)
 void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  CAN Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
+static struct resource can_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_CAN,
+               .end    = AT91SAM9263_BASE_CAN + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_CAN,
+               .end    = AT91SAM9263_ID_CAN,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_can_device = {
+       .name           = "at91_can",
+       .id             = -1,
+       .resource       = can_resources,
+       .num_resources  = ARRAY_SIZE(can_resources),
+};
+
+void __init at91_add_device_can(struct at91_can_data *data)
+{
+       at91_set_A_periph(AT91_PIN_PA13, 0);    /* CANTX */
+       at91_set_A_periph(AT91_PIN_PA14, 0);    /* CANRX */
+       at91sam9263_can_device.dev.platform_data = data;
+
+       platform_device_register(&at91sam9263_can_device);
+}
+#else
+void __init at91_add_device_can(struct at91_can_data *data) {}
+#endif
 
 /* --------------------------------------------------------------------
  *  LCD Controller
index 57d52528f2247950b90c9b4010af813595eeedcc..e6268b3cbe8ddc21b5c3619a5fb71d26e9c235a4 100644 (file)
@@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
        }
 };
 
+/*
+ * CAN
+ */
+static void sam9263ek_transceiver_switch(int on)
+{
+       if (on) {
+               at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
+               at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
+       } else {
+               at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
+               at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
+       }
+}
+
+static struct at91_can_data ek_can_data = {
+       .transceiver_switch = sam9263ek_transceiver_switch,
+};
 
 static void __init ek_board_init(void)
 {
@@ -431,6 +448,8 @@ static void __init ek_board_init(void)
        /* LEDs */
        at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
        at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+       /* CAN */
+       at91_add_device_can(&ek_can_data);
 }
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
index e6afff849b85e5475155b344123387276958a694..134731cd9fdfae6a7deeeca5b96537878a9a2dfc 100644 (file)
@@ -179,6 +179,12 @@ extern void __init at91_add_device_isi(void);
  /* Touchscreen Controller */
 extern void __init at91_add_device_tsadcc(void);
 
+/* CAN */
+struct at91_can_data {
+       void (*transceiver_switch)(int on);
+};
+extern void __init at91_add_device_can(struct at91_can_data *data);
+
  /* LEDs */
 extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
index 2de64065aa1b203b113f62e8428319f140b0b382..29e66d603d3c6977d55a44611a0baa05f106331e 100644 (file)
@@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
        he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
                CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
        if (he_dev->rbps_base == NULL) {
-               hprintk("failed to alloc rbps\n");
-               return -ENOMEM;
+               hprintk("failed to alloc rbps_base\n");
+               goto out_destroy_rbps_pool;
        }
        memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
        he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+       if (he_dev->rbps_virt == NULL) {
+               hprintk("failed to alloc rbps_virt\n");
+               goto out_free_rbps_base;
+       }
 
        for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
                dma_addr_t dma_handle;
@@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
                cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
-                       return -ENOMEM;
+                       goto out_free_rbps_virt;
 
                he_dev->rbps_virt[i].virt = cpuaddr;
                he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
                        CONFIG_RBPL_BUFSIZE, 8, 0);
        if (he_dev->rbpl_pool == NULL) {
                hprintk("unable to create rbpl pool\n");
-               return -ENOMEM;
+               goto out_free_rbps_virt;
        }
 
        he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
                CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
        if (he_dev->rbpl_base == NULL) {
-               hprintk("failed to alloc rbpl\n");
-               return -ENOMEM;
+               hprintk("failed to alloc rbpl_base\n");
+               goto out_destroy_rbpl_pool;
        }
        memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
        he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+       if (he_dev->rbpl_virt == NULL) {
+               hprintk("failed to alloc rbpl_virt\n");
+               goto out_free_rbpl_base;
+       }
 
        for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
                dma_addr_t dma_handle;
@@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
                cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
-                       return -ENOMEM;
+                       goto out_free_rbpl_virt;
 
                he_dev->rbpl_virt[i].virt = cpuaddr;
                he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
                CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
        if (he_dev->rbrq_base == NULL) {
                hprintk("failed to allocate rbrq\n");
-               return -ENOMEM;
+               goto out_free_rbpl_virt;
        }
        memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 
@@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
                CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
        if (he_dev->tbrq_base == NULL) {
                hprintk("failed to allocate tbrq\n");
-               return -ENOMEM;
+               goto out_free_rbpq_base;
        }
        memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 
@@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
        he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
 
        return 0;
+
+out_free_rbpq_base:
+       pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
+                       sizeof(struct he_rbrq), he_dev->rbrq_base,
+                       he_dev->rbrq_phys);
+       i = CONFIG_RBPL_SIZE;
+out_free_rbpl_virt:
+       while (--i)
+               pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
+                               he_dev->rbps_base[i].phys);
+       kfree(he_dev->rbpl_virt);
+
+out_free_rbpl_base:
+       pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
+                       sizeof(struct he_rbp), he_dev->rbpl_base,
+                       he_dev->rbpl_phys);
+out_destroy_rbpl_pool:
+       pci_pool_destroy(he_dev->rbpl_pool);
+
+       i = CONFIG_RBPL_SIZE;
+out_free_rbps_virt:
+       while (--i)
+               pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
+                               he_dev->rbpl_base[i].phys);
+       kfree(he_dev->rbps_virt);
+
+out_free_rbps_base:
+       pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
+                       sizeof(struct he_rbp), he_dev->rbps_base,
+                       he_dev->rbps_phys);
+out_destroy_rbps_pool:
+       pci_pool_destroy(he_dev->rbps_pool);
+       return -ENOMEM;
 }
 
 static int __devinit
index efa2808dd94d278cfae1fe54f0b60d2b829ac27d..1a9332e4efe0847aea86548b2e58e9fcd77b1268 100644 (file)
@@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp)
 SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
 SOLOS_ATTR_RO(InterleaveRDn)
 SOLOS_ATTR_RO(InterleaveRUp)
+SOLOS_ATTR_RO(BisRDn)
+SOLOS_ATTR_RO(BisRUp)
+SOLOS_ATTR_RO(INPdown)
+SOLOS_ATTR_RO(INPup)
 SOLOS_ATTR_RO(ShowtimeStart)
 SOLOS_ATTR_RO(ATURVendor)
 SOLOS_ATTR_RO(ATUCCountry)
@@ -62,6 +66,13 @@ SOLOS_ATTR_RW(Defaults)
 SOLOS_ATTR_RW(LineMode)
 SOLOS_ATTR_RW(Profile)
 SOLOS_ATTR_RW(DetectNoise)
+SOLOS_ATTR_RW(BisAForceSNRMarginDn)
+SOLOS_ATTR_RW(BisMForceSNRMarginDn)
+SOLOS_ATTR_RW(BisAMaxMargin)
+SOLOS_ATTR_RW(BisMMaxMargin)
+SOLOS_ATTR_RW(AnnexAForceSNRMarginDn)
+SOLOS_ATTR_RW(AnnexAMaxMargin)
+SOLOS_ATTR_RW(AnnexMMaxMargin)
 SOLOS_ATTR_RO(SupportedAnnexes)
 SOLOS_ATTR_RO(Status)
 SOLOS_ATTR_RO(TotalStart)
index 307321b32cb35f43396f26631ce49069f59ce529..c5f5186d62a3160404a50b5819c440239b311870 100644 (file)
 #define RX_DMA_ADDR(port)      (0x30 + (4 * (port)))
 
 #define DATA_RAM_SIZE  32768
-#define BUF_SIZE       4096
+#define BUF_SIZE       2048
+#define OLD_BUF_SIZE   4096 /* For FPGA versions <= 2*/
 #define FPGA_PAGE      528 /* FPGA flash page size*/
 #define SOLOS_PAGE     512 /* Solos flash page size*/
 #define FPGA_BLOCK     (FPGA_PAGE * 8) /* FPGA flash block size*/
 #define SOLOS_BLOCK    (SOLOS_PAGE * 8) /* Solos flash block size*/
 
-#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
-#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
+#define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
+#define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
+#define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2)
 
 #define RX_DMA_SIZE    2048
 
+#define FPGA_VERSION(a,b) (((a) << 8) + (b))
+#define LEGACY_BUFFERS 2
+#define DMA_SUPPORTED  4
+
 static int reset = 0;
 static int atmdebug = 0;
 static int firmware_upgrade = 0;
 static int fpga_upgrade = 0;
+static int db_firmware_upgrade = 0;
+static int db_fpga_upgrade = 0;
 
 struct pkt_hdr {
        __le16 size;
@@ -116,6 +124,8 @@ struct solos_card {
        wait_queue_head_t param_wq;
        wait_queue_head_t fw_wq;
        int using_dma;
+       int fpga_version;
+       int buffer_size;
 };
 
 
@@ -136,10 +146,14 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
 MODULE_PARM_DESC(atmdebug, "Print ATM data");
 MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
 MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
+MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade");
+MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade");
 module_param(reset, int, 0444);
 module_param(atmdebug, int, 0644);
 module_param(firmware_upgrade, int, 0444);
 module_param(fpga_upgrade, int, 0444);
+module_param(db_firmware_upgrade, int, 0444);
+module_param(db_fpga_upgrade, int, 0444);
 
 static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
                       struct atm_vcc *vcc);
@@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip)
        if (chip == 0) {
                fw_name = "solos-FPGA.bin";
                blocksize = FPGA_BLOCK;
-       } else {
+       } 
+       
+       if (chip == 1) {
                fw_name = "solos-Firmware.bin";
                blocksize = SOLOS_BLOCK;
        }
+       
+       if (chip == 2){
+               if (card->fpga_version > LEGACY_BUFFERS){
+                       fw_name = "solos-db-FPGA.bin";
+                       blocksize = FPGA_BLOCK;
+               } else {
+                       dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
+                       return -EPERM;
+               }
+       }
+       
+       if (chip == 3){
+               if (card->fpga_version > LEGACY_BUFFERS){
+                       fw_name = "solos-Firmware.bin";
+                       blocksize = SOLOS_BLOCK;
+               } else {
+               dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
+               return -EPERM;
+               }
+       }
 
        if (request_firmware(&fw, fw_name, &card->dev->dev))
                return -ENOENT;
@@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
        data32 = ioread32(card->config_regs + FPGA_MODE); 
 
        /* Set mode to Chip Erase */
-       dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n",
-                chip?"Solos":"FPGA");
+       if(chip == 0 || chip == 2)
+               dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n");
+       if(chip == 1 || chip == 3)
+               dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n");
        iowrite32((chip * 2), card->config_regs + FLASH_MODE);
 
 
@@ -557,7 +595,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
                /* Copy block to buffer, swapping each 16 bits */
                for(i = 0; i < blocksize; i += 4) {
                        uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
-                       iowrite32(word, RX_BUF(card, 3) + i);
+                       if(card->fpga_version > LEGACY_BUFFERS)
+                               iowrite32(word, FLASH_BUF + i);
+                       else
+                               iowrite32(word, RX_BUF(card, 3) + i);
                }
 
                /* Specify block number and then trigger flash write */
@@ -630,6 +671,10 @@ void solos_bh(unsigned long card_arg)
                                memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
 
                                size = le16_to_cpu(header->size);
+                               if (size > (card->buffer_size - sizeof(*header))){
+                                       dev_warn(&card->dev->dev, "Invalid buffer size\n");
+                                       continue;
+                               }
 
                                skb = alloc_skb(size + 1, GFP_ATOMIC);
                                if (!skb) {
@@ -1094,12 +1139,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        fpga_ver = (data32 & 0x0000FFFF);
        major_ver = ((data32 & 0xFF000000) >> 24);
        minor_ver = ((data32 & 0x00FF0000) >> 16);
+       card->fpga_version = FPGA_VERSION(major_ver,minor_ver);
+       if (card->fpga_version > LEGACY_BUFFERS)
+               card->buffer_size = BUF_SIZE;
+       else
+               card->buffer_size = OLD_BUF_SIZE;
        dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
                 major_ver, minor_ver, fpga_ver);
 
-       if (0 && fpga_ver > 27)
+       if (card->fpga_version >= DMA_SUPPORTED){
                card->using_dma = 1;
-       else {
+       } else {
+               card->using_dma = 0;
                /* Set RX empty flag for all ports */
                iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
        }
@@ -1131,6 +1182,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (firmware_upgrade)
                flash_upgrade(card, 1);
 
+       if (db_fpga_upgrade)
+               flash_upgrade(card, 2);
+
+       if (db_firmware_upgrade)
+               flash_upgrade(card, 3);
+
        err = atm_init(card);
        if (err)
                goto out_free_irq;
index 462d9f59c53aacfcb980b8326c005e6a53c10f48..83a1922e68e0a8750705c03087786c71f4cea084 100644 (file)
@@ -87,7 +87,7 @@
 
 /* These identify the driver base version and may not be removed. */
 static char version[] =
-KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
+DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
index 21333c18f3441e023b3d03da13d925e85bbfeb1a..f9fbd52b799b0a1f931dc709b7473980e9fe5e0c 100644 (file)
@@ -1875,7 +1875,7 @@ config 68360_ENET
 
 config FEC
        bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
-       depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35
+       depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25
        help
          Say Y here if you want to use the built-in 10/100 Fast ethernet
          controller on some Motorola ColdFire and Freescale i.MX processors.
index be2c6cfe6e84cc55e7a71b2c63adad1057dc2a4b..1372e9a99f5b29eb8e92aefc39404234977ceae0 100644 (file)
@@ -2296,7 +2296,7 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
        u32 ctrl;
        u32 mac_ctrl_data;
        u32 master_ctrl_data;
-       u32 wol_ctrl_data;
+       u32 wol_ctrl_data = 0;
        u16 mii_bmsr_data;
        u16 save_autoneg_advertised;
        u16 mii_intr_status_data;
index ba48220df16a394cb157c8e9eb373de0408004a9..490d3b38e0cbaf299c57a097d20b1911f0ff03a8 100644 (file)
@@ -377,10 +377,19 @@ struct atl1e_hw {
  */
 struct atl1e_tx_buffer {
        struct sk_buff *skb;
+       u16 flags;
+#define ATL1E_TX_PCIMAP_SINGLE         0x0001
+#define ATL1E_TX_PCIMAP_PAGE           0x0002
+#define ATL1E_TX_PCIMAP_TYPE_MASK      0x0003
        u16 length;
        dma_addr_t dma;
 };
 
+#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {              \
+       ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;       \
+       ((tx_buff)->flags) |= (type);                           \
+       } while (0)
+
 struct atl1e_rx_page {
        dma_addr_t      dma;    /* receive rage DMA address */
        u8              *addr;   /* receive rage virtual address */
index 69b830f4b68fc3f9d85779f095feff2cb1338478..955da733c2ad9957320aafa545351b771c40056a 100644 (file)
@@ -635,7 +635,11 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
        for (index = 0; index < ring_count; index++) {
                tx_buffer = &tx_ring->tx_buffer[index];
                if (tx_buffer->dma) {
-                       pci_unmap_page(pdev, tx_buffer->dma,
+                       if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+                               pci_unmap_single(pdev, tx_buffer->dma,
+                                       tx_buffer->length, PCI_DMA_TODEVICE);
+                       else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+                               pci_unmap_page(pdev, tx_buffer->dma,
                                        tx_buffer->length, PCI_DMA_TODEVICE);
                        tx_buffer->dma = 0;
                }
@@ -1220,7 +1224,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
        while (next_to_clean != hw_next_to_clean) {
                tx_buffer = &tx_ring->tx_buffer[next_to_clean];
                if (tx_buffer->dma) {
-                       pci_unmap_page(adapter->pdev, tx_buffer->dma,
+                       if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+                               pci_unmap_single(adapter->pdev, tx_buffer->dma,
+                                       tx_buffer->length, PCI_DMA_TODEVICE);
+                       else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+                               pci_unmap_page(adapter->pdev, tx_buffer->dma,
                                        tx_buffer->length, PCI_DMA_TODEVICE);
                        tx_buffer->dma = 0;
                }
@@ -1741,6 +1749,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                tx_buffer->length = map_len;
                tx_buffer->dma = pci_map_single(adapter->pdev,
                                        skb->data, hdr_len, PCI_DMA_TODEVICE);
+               ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
                mapped_len += map_len;
                use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
                use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1766,6 +1775,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                tx_buffer->dma =
                        pci_map_single(adapter->pdev, skb->data + mapped_len,
                                        map_len, PCI_DMA_TODEVICE);
+               ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
                mapped_len  += map_len;
                use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
                use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1801,6 +1811,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                                                (i * MAX_TX_BUF_LEN),
                                                tx_buffer->length,
                                                PCI_DMA_TODEVICE);
+                       ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
                        use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
                        use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
                                        ((cpu_to_le32(tx_buffer->length) &
index 0189dcd36f31b9c4fd778763c87e30e671df8059..e046943ef29dc6c9243bb84ad0c5ab5fcdde19bf 100644 (file)
@@ -847,23 +847,22 @@ static int b44_poll(struct napi_struct *napi, int budget)
 {
        struct b44 *bp = container_of(napi, struct b44, napi);
        int work_done;
+       unsigned long flags;
 
-       spin_lock_irq(&bp->lock);
+       spin_lock_irqsave(&bp->lock, flags);
 
        if (bp->istat & (ISTAT_TX | ISTAT_TO)) {
                /* spin_lock(&bp->tx_lock); */
                b44_tx(bp);
                /* spin_unlock(&bp->tx_lock); */
        }
-       spin_unlock_irq(&bp->lock);
+       spin_unlock_irqrestore(&bp->lock, flags);
 
        work_done = 0;
        if (bp->istat & ISTAT_RX)
                work_done += b44_rx(bp, budget);
 
        if (bp->istat & ISTAT_ERRORS) {
-               unsigned long flags;
-
                spin_lock_irqsave(&bp->lock, flags);
                b44_halt(bp);
                b44_init_rings(bp);
index 13b72ce870de62e5f09e7f0006225a83f8b948bf..684c6fe24c8d538daa5145c803ac3c66e717fec2 100644 (file)
@@ -362,5 +362,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
                u16 num_popped);
 extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
+extern void netdev_stats_update(struct be_adapter *adapter);
 extern int be_load_fw(struct be_adapter *adapter, u8 *func);
 #endif                         /* BE_H */
index 1db092498309ca8a4fe840a2e6f7c5d4cdd2e30a..3dd76c4170bfc000657f4b65713b662d20c8de04 100644 (file)
@@ -59,15 +59,22 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
 
        compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
                                CQE_STATUS_COMPL_MASK;
-       if (compl_status != MCC_STATUS_SUCCESS) {
+       if (compl_status == MCC_STATUS_SUCCESS) {
+               if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) {
+                       struct be_cmd_resp_get_stats *resp =
+                                               adapter->stats.cmd.va;
+                       be_dws_le_to_cpu(&resp->hw_stats,
+                                               sizeof(resp->hw_stats));
+                       netdev_stats_update(adapter);
+               }
+       } else if (compl_status != MCC_STATUS_NOT_SUPPORTED) {
                extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
                                CQE_STATUS_EXTD_MASK;
                dev_warn(&adapter->pdev->dev,
                        "Error in cmd completion: status(compl/extd)=%d/%d\n",
                        compl_status, extd_status);
-               return -1;
        }
-       return 0;
+       return compl_status;
 }
 
 /* Link state evt is a string of bytes; no need for endian swapping */
@@ -97,10 +104,10 @@ static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
        return NULL;
 }
 
-void be_process_mcc(struct be_adapter *adapter)
+int be_process_mcc(struct be_adapter *adapter)
 {
        struct be_mcc_compl *compl;
-       int num = 0;
+       int num = 0, status = 0;
 
        spin_lock_bh(&adapter->mcc_cq_lock);
        while ((compl = be_mcc_compl_get(adapter))) {
@@ -111,38 +118,47 @@ void be_process_mcc(struct be_adapter *adapter)
                        /* Interpret compl as a async link evt */
                        be_async_link_state_process(adapter,
                                (struct be_async_event_link_state *) compl);
-               } else {
-                       be_mcc_compl_process(adapter, compl);
-                       atomic_dec(&adapter->mcc_obj.q.used);
+               } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
+                               status = be_mcc_compl_process(adapter, compl);
+                               atomic_dec(&adapter->mcc_obj.q.used);
                }
                be_mcc_compl_use(compl);
                num++;
        }
+
        if (num)
                be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num);
+
        spin_unlock_bh(&adapter->mcc_cq_lock);
+       return status;
 }
 
 /* Wait till no more pending mcc requests are present */
-static void be_mcc_wait_compl(struct be_adapter *adapter)
+static int be_mcc_wait_compl(struct be_adapter *adapter)
 {
-#define mcc_timeout            50000 /* 5s timeout */
-       int i;
+#define mcc_timeout            120000 /* 12s timeout */
+       int i, status;
        for (i = 0; i < mcc_timeout; i++) {
-               be_process_mcc(adapter);
+               status = be_process_mcc(adapter);
+               if (status)
+                       return status;
+
                if (atomic_read(&adapter->mcc_obj.q.used) == 0)
                        break;
                udelay(100);
        }
-       if (i == mcc_timeout)
+       if (i == mcc_timeout) {
                dev_err(&adapter->pdev->dev, "mccq poll timed out\n");
+               return -1;
+       }
+       return 0;
 }
 
 /* Notify MCC requests and wait for completion */
-static void be_mcc_notify_wait(struct be_adapter *adapter)
+static int be_mcc_notify_wait(struct be_adapter *adapter)
 {
        be_mcc_notify(adapter);
-       be_mcc_wait_compl(adapter);
+       return be_mcc_wait_compl(adapter);
 }
 
 static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
@@ -173,7 +189,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
  * Insert the mailbox address into the doorbell in two steps
  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
  */
-static int be_mbox_notify(struct be_adapter *adapter)
+static int be_mbox_notify_wait(struct be_adapter *adapter)
 {
        int status;
        u32 val = 0;
@@ -182,8 +198,6 @@ static int be_mbox_notify(struct be_adapter *adapter)
        struct be_mcc_mailbox *mbox = mbox_mem->va;
        struct be_mcc_compl *compl = &mbox->compl;
 
-       memset(compl, 0, sizeof(*compl));
-
        val |= MPU_MAILBOX_DB_HI_MASK;
        /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
        val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -310,34 +324,40 @@ static u32 eq_delay_to_mult(u32 usec_delay)
        return multiplier;
 }
 
-static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
+static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
 {
-       return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
+       struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
+       struct be_mcc_wrb *wrb
+               = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
+       memset(wrb, 0, sizeof(*wrb));
+       return wrb;
 }
 
-static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq)
+static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
 {
-       struct be_mcc_wrb *wrb = NULL;
-       if (atomic_read(&mccq->used) < mccq->len) {
-               wrb = queue_head_node(mccq);
-               queue_head_inc(mccq);
-               atomic_inc(&mccq->used);
-               memset(wrb, 0, sizeof(*wrb));
-       }
+       struct be_queue_info *mccq = &adapter->mcc_obj.q;
+       struct be_mcc_wrb *wrb;
+
+       BUG_ON(atomic_read(&mccq->used) >= mccq->len);
+       wrb = queue_head_node(mccq);
+       queue_head_inc(mccq);
+       atomic_inc(&mccq->used);
+       memset(wrb, 0, sizeof(*wrb));
        return wrb;
 }
 
 int be_cmd_eq_create(struct be_adapter *adapter,
                struct be_queue_info *eq, int eq_delay)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_eq_create *req = embedded_payload(wrb);
-       struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_eq_create *req;
        struct be_dma_mem *q_mem = &eq->dma_mem;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -359,25 +379,29 @@ int be_cmd_eq_create(struct be_adapter *adapter,
 
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
+               struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
                eq->id = le16_to_cpu(resp->eq_id);
                eq->created = true;
        }
+
        spin_unlock(&adapter->mbox_lock);
        return status;
 }
 
+/* Uses mbox */
 int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
                        u8 type, bool permanent, u32 if_handle)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_mac_query *req = embedded_payload(wrb);
-       struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_mac_query *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -388,27 +412,32 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
        if (permanent) {
                req->permanent = 1;
        } else {
-               req->if_id = cpu_to_le16((u16)if_handle);
+               req->if_id = cpu_to_le16((u16) if_handle);
                req->permanent = 0;
        }
 
-       status = be_mbox_notify(adapter);
-       if (!status)
+       status = be_mbox_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
                memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
+       }
 
        spin_unlock(&adapter->mbox_lock);
        return status;
 }
 
+/* Uses synchronous MCCQ */
 int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
                u32 if_id, u32 *pmac_id)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_pmac_add *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_pmac_add *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -418,24 +447,27 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
        req->if_id = cpu_to_le32(if_id);
        memcpy(req->mac_address, mac_addr, ETH_ALEN);
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
                *pmac_id = le32_to_cpu(resp->pmac_id);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
+/* Uses synchronous MCCQ */
 int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_pmac_del *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_pmac_del *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -445,25 +477,29 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
        req->if_id = cpu_to_le32(if_id);
        req->pmac_id = cpu_to_le32(pmac_id);
 
-       status = be_mbox_notify(adapter);
-       spin_unlock(&adapter->mbox_lock);
+       status = be_mcc_notify_wait(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
 
        return status;
 }
 
+/* Uses Mbox */
 int be_cmd_cq_create(struct be_adapter *adapter,
                struct be_queue_info *cq, struct be_queue_info *eq,
                bool sol_evts, bool no_delay, int coalesce_wm)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_cq_create *req = embedded_payload(wrb);
-       struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_cq_create *req;
        struct be_dma_mem *q_mem = &cq->dma_mem;
-       void *ctxt = &req->context;
+       void *ctxt;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
+       ctxt = &req->context;
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -486,11 +522,13 @@ int be_cmd_cq_create(struct be_adapter *adapter,
 
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
+               struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
                cq->id = le16_to_cpu(resp->cq_id);
                cq->created = true;
        }
+
        spin_unlock(&adapter->mbox_lock);
 
        return status;
@@ -508,14 +546,17 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
                        struct be_queue_info *mccq,
                        struct be_queue_info *cq)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_mcc_create *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_mcc_create *req;
        struct be_dma_mem *q_mem = &mccq->dma_mem;
-       void *ctxt = &req->context;
+       void *ctxt;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
+       ctxt = &req->context;
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -534,7 +575,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
 
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
                mccq->id = le16_to_cpu(resp->id);
@@ -549,15 +590,17 @@ int be_cmd_txq_create(struct be_adapter *adapter,
                        struct be_queue_info *txq,
                        struct be_queue_info *cq)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_eth_tx_create *req;
        struct be_dma_mem *q_mem = &txq->dma_mem;
-       void *ctxt = &req->context;
+       void *ctxt;
        int status;
-       u32 len_encoded;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
+       ctxt = &req->context;
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -568,10 +611,8 @@ int be_cmd_txq_create(struct be_adapter *adapter,
        req->ulp_num = BE_ULP1_NUM;
        req->type = BE_ETH_TX_RING_TYPE_STANDARD;
 
-       len_encoded = fls(txq->len); /* log2(len) + 1 */
-       if (len_encoded == 16)
-               len_encoded = 0;
-       AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded);
+       AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt,
+               be_encoded_q_len(txq->len));
        AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt,
                        be_pci_func(adapter));
        AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1);
@@ -581,28 +622,32 @@ int be_cmd_txq_create(struct be_adapter *adapter,
 
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
                txq->id = le16_to_cpu(resp->cid);
                txq->created = true;
        }
+
        spin_unlock(&adapter->mbox_lock);
 
        return status;
 }
 
+/* Uses mbox */
 int be_cmd_rxq_create(struct be_adapter *adapter,
                struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
                u16 max_frame_size, u32 if_id, u32 rss)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_eth_rx_create *req;
        struct be_dma_mem *q_mem = &rxq->dma_mem;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -617,29 +662,34 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
        req->max_frame_size = cpu_to_le16(max_frame_size);
        req->rss_queue = cpu_to_le32(rss);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
                rxq->id = le16_to_cpu(resp->id);
                rxq->created = true;
        }
+
        spin_unlock(&adapter->mbox_lock);
 
        return status;
 }
 
-/* Generic destroyer function for all types of queues */
+/* Generic destroyer function for all types of queues
+ * Uses Mbox
+ */
 int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
                int queue_type)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_q_destroy *req;
        u8 subsys = 0, opcode = 0;
        int status;
 
        spin_lock(&adapter->mbox_lock);
 
-       memset(wrb, 0, sizeof(*wrb));
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
+
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        switch (queue_type) {
@@ -669,23 +719,27 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
        be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
        req->id = cpu_to_le16(q->id);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
 
        spin_unlock(&adapter->mbox_lock);
 
        return status;
 }
 
-/* Create an rx filtering policy configuration on an i/f */
+/* Create an rx filtering policy configuration on an i/f
+ * Uses mbox
+ */
 int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
                bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_if_create *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_if_create *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -694,10 +748,11 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
 
        req->capability_flags = cpu_to_le32(flags);
        req->enable_flags = cpu_to_le32(flags);
+       req->pmac_invalid = pmac_invalid;
        if (!pmac_invalid)
                memcpy(req->mac_addr, mac, ETH_ALEN);
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
                *if_handle = le32_to_cpu(resp->interface_id);
@@ -709,14 +764,17 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
        return status;
 }
 
+/* Uses mbox */
 int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_if_destroy *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_if_destroy *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -724,7 +782,8 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
                OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
 
        req->interface_id = cpu_to_le32(interface_id);
-       status = be_mbox_notify(adapter);
+
+       status = be_mbox_notify_wait(adapter);
 
        spin_unlock(&adapter->mbox_lock);
 
@@ -733,20 +792,22 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 
 /* Get stats is a non embedded command: the request is not embedded inside
  * WRB but is a separate dma memory block
+ * Uses asynchronous MCC
  */
 int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_get_stats *req = nonemb_cmd->va;
-       struct be_sge *sge = nonembedded_sgl(wrb);
-       int status;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_stats *req;
+       struct be_sge *sge;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
 
-       memset(req, 0, sizeof(*req));
+       wrb = wrb_from_mccq(adapter);
+       req = nonemb_cmd->va;
+       sge = nonembedded_sgl(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
+       wrb->tag0 = OPCODE_ETH_GET_STATISTICS;
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
                OPCODE_ETH_GET_STATISTICS, sizeof(*req));
@@ -754,59 +815,61 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
        sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
        sge->len = cpu_to_le32(nonemb_cmd->size);
 
-       status = be_mbox_notify(adapter);
-       if (!status) {
-               struct be_cmd_resp_get_stats *resp = nonemb_cmd->va;
-               be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats));
-       }
+       be_mcc_notify(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
-       return status;
+       spin_unlock_bh(&adapter->mcc_lock);
+       return 0;
 }
 
+/* Uses synchronous mcc */
 int be_cmd_link_status_query(struct be_adapter *adapter,
                        bool *link_up)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_link_status *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_link_status *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        *link_up = false;
-       memset(wrb, 0, sizeof(*wrb));
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req));
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
                if (resp->mac_speed != PHY_LINK_SPEED_ZERO)
                        *link_up = true;
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
+/* Uses Mbox */
 int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_get_fw_version *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fw_version *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_GET_FW_VERSION, sizeof(*req));
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
                strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
@@ -816,15 +879,18 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
        return status;
 }
 
-/* set the EQ delay interval of an EQ to specified value */
+/* set the EQ delay interval of an EQ to specified value
+ * Uses async mcc
+ */
 int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb);
-       int status;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_modify_eq_delay *req;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -836,21 +902,24 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
        req->delay[0].phase = 0;
        req->delay[0].delay_multiplier = cpu_to_le32(eqd);
 
-       status = be_mbox_notify(adapter);
+       be_mcc_notify(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
-       return status;
+       spin_unlock_bh(&adapter->mcc_lock);
+       return 0;
 }
 
+/* Uses sycnhronous mcc */
 int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
                        u32 num, bool untagged, bool promiscuous)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_vlan_config *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_vlan_config *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -866,23 +935,24 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
                        req->num_vlan * sizeof(vtag_array[0]));
        }
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
-/* Use MCC for this command as it may be called in BH context */
+/* Uses MCC for this command as it may be called in BH context
+ * Uses synchronous mcc
+ */
 int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_promiscuous_config *req;
+       int status;
 
        spin_lock_bh(&adapter->mcc_lock);
 
-       wrb = wrb_from_mcc(&adapter->mcc_obj.q);
-       BUG_ON(!wrb);
-
+       wrb = wrb_from_mccq(adapter);
        req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -895,14 +965,14 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
        else
                req->port0_promiscuous = en;
 
-       be_mcc_notify_wait(adapter);
+       status = be_mcc_notify_wait(adapter);
 
        spin_unlock_bh(&adapter->mcc_lock);
-       return 0;
+       return status;
 }
 
 /*
- * Use MCC for this command as it may be called in BH context
+ * Uses MCC for this command as it may be called in BH context
  * (mc == NULL) => multicast promiscous
  */
 int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
@@ -914,9 +984,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 
        spin_lock_bh(&adapter->mcc_lock);
 
-       wrb = wrb_from_mcc(&adapter->mcc_obj.q);
-       BUG_ON(!wrb);
-
+       wrb = wrb_from_mccq(adapter);
        req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -944,15 +1012,17 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
        return 0;
 }
 
+/* Uses synchrounous mcc */
 int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_set_flow_control *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_set_flow_control *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       spin_lock_bh(&adapter->mcc_lock);
 
-       memset(wrb, 0, sizeof(*wrb));
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -962,28 +1032,30 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
        req->tx_flow_control = cpu_to_le16((u16)tx_fc);
        req->rx_flow_control = cpu_to_le16((u16)rx_fc);
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
+/* Uses sycn mcc */
 int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_get_flow_control *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_flow_control *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       spin_lock_bh(&adapter->mcc_lock);
 
-       memset(wrb, 0, sizeof(*wrb));
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req));
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_get_flow_control *resp =
                                                embedded_payload(wrb);
@@ -991,26 +1063,28 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
                *rx_fc = le16_to_cpu(resp->rx_flow_control);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
+/* Uses mbox */
 int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_query_fw_cfg *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
 
-       memset(wrb, 0, sizeof(*wrb));
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
        if (!status) {
                struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
                *port_num = le32_to_cpu(resp->phys_port);
@@ -1020,22 +1094,24 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num)
        return status;
 }
 
+/* Uses mbox */
 int be_cmd_reset_function(struct be_adapter *adapter)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
-       struct be_cmd_req_hdr *req = embedded_payload(wrb);
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_hdr *req;
        int status;
 
        spin_lock(&adapter->mbox_lock);
 
-       memset(wrb, 0, sizeof(*wrb));
+       wrb = wrb_from_mbox(adapter);
+       req = embedded_payload(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
        be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
 
-       status = be_mbox_notify(adapter);
+       status = be_mbox_notify_wait(adapter);
 
        spin_unlock(&adapter->mbox_lock);
        return status;
@@ -1044,13 +1120,17 @@ int be_cmd_reset_function(struct be_adapter *adapter)
 int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
                        u32 flash_type, u32 flash_opcode, u32 buf_size)
 {
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
+       struct be_mcc_wrb *wrb;
        struct be_cmd_write_flashrom *req = cmd->va;
-       struct be_sge *sge = nonembedded_sgl(wrb);
+       struct be_sge *sge;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       req = embedded_payload(wrb);
+       sge = nonembedded_sgl(wrb);
+
        be_wrb_hdr_prepare(wrb, cmd->size, false, 1);
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
@@ -1063,8 +1143,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        req->params.op_code = cpu_to_le32(flash_opcode);
        req->params.data_buf_size = cpu_to_le32(buf_size);
 
-       status = be_mbox_notify(adapter);
+       status = be_mcc_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
index fd7028e5b78ea73fa519089d30621348efe1c8d6..93e432f3d926f784ecf586375ceb1c0c54c76183 100644 (file)
@@ -61,7 +61,8 @@ enum {
 /* The command is completing because the queue was getting flushed */
        MCC_STATUS_QUEUE_FLUSHING = 0x4,
 /* The command is completing with a DMA error */
-       MCC_STATUS_DMA_FAILED = 0x5
+       MCC_STATUS_DMA_FAILED = 0x5,
+       MCC_STATUS_NOT_SUPPORTED = 0x66
 };
 
 #define CQE_STATUS_COMPL_MASK          0xFFFF
@@ -761,7 +762,7 @@ extern int be_cmd_get_flow_control(struct be_adapter *adapter,
                        u32 *tx_fc, u32 *rx_fc);
 extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num);
 extern int be_cmd_reset_function(struct be_adapter *adapter);
-extern void be_process_mcc(struct be_adapter *adapter);
+extern int be_process_mcc(struct be_adapter *adapter);
 extern int be_cmd_write_flashrom(struct be_adapter *adapter,
                        struct be_dma_mem *cmd, u32 flash_oper,
                        u32 flash_opcode, u32 buf_size);
index ce11bba2cb6764a99cf577977c3e8dd9ee3eb00d..409cf05959034737273f6b2cb8371a2347102059 100644 (file)
@@ -135,7 +135,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        return status;
 }
 
-static void netdev_stats_update(struct be_adapter *adapter)
+void netdev_stats_update(struct be_adapter *adapter)
 {
        struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
        struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
@@ -431,8 +431,7 @@ static int make_tx_wrbs(struct be_adapter *adapter,
 }
 
 static netdev_tx_t be_xmit(struct sk_buff *skb,
-                                struct net_device *netdev)
-
+                       struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_tx_obj *tx_obj = &adapter->tx_obj;
@@ -490,11 +489,11 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
  * program them in BE.  If more than BE_NUM_VLANS_SUPPORTED are configured,
  * set the BE in promiscuous VLAN mode.
  */
-static void be_vid_config(struct net_device *netdev)
+static int be_vid_config(struct be_adapter *adapter)
 {
-       struct be_adapter *adapter = netdev_priv(netdev);
        u16 vtag[BE_NUM_VLANS_SUPPORTED];
        u16 ntags = 0, i;
+       int status;
 
        if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED)  {
                /* Construct VLAN Table to give to HW */
@@ -504,12 +503,13 @@ static void be_vid_config(struct net_device *netdev)
                                ntags++;
                        }
                }
-               be_cmd_vlan_config(adapter, adapter->if_handle,
-                       vtag, ntags, 1, 0);
+               status = be_cmd_vlan_config(adapter, adapter->if_handle,
+                                       vtag, ntags, 1, 0);
        } else {
-               be_cmd_vlan_config(adapter, adapter->if_handle,
-                       NULL, 0, 1, 1);
+               status = be_cmd_vlan_config(adapter, adapter->if_handle,
+                                       NULL, 0, 1, 1);
        }
+       return status;
 }
 
 static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
@@ -532,7 +532,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
        adapter->num_vlans++;
        adapter->vlan_tag[vid] = 1;
 
-       be_vid_config(netdev);
+       be_vid_config(adapter);
 }
 
 static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
@@ -543,7 +543,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
        adapter->vlan_tag[vid] = 0;
 
        vlan_group_set_device(adapter->vlan_grp, vid, NULL);
-       be_vid_config(netdev);
+       be_vid_config(adapter);
 }
 
 static void be_set_multicast_list(struct net_device *netdev)
@@ -1444,12 +1444,8 @@ static void be_worker(struct work_struct *work)
 {
        struct be_adapter *adapter =
                container_of(work, struct be_adapter, work.work);
-       int status;
 
-       /* Get Stats */
-       status = be_cmd_get_stats(adapter, &adapter->stats.cmd);
-       if (!status)
-               netdev_stats_update(adapter);
+       be_cmd_get_stats(adapter, &adapter->stats.cmd);
 
        /* Set EQ delay */
        be_rx_eqd_update(adapter);
@@ -1622,11 +1618,6 @@ static int be_setup(struct be_adapter *adapter)
        if (status != 0)
                goto do_none;
 
-       be_vid_config(netdev);
-
-       status = be_cmd_set_flow_control(adapter, true, true);
-       if (status != 0)
-               goto if_destroy;
 
        status = be_tx_queues_create(adapter);
        if (status != 0)
@@ -1640,8 +1631,17 @@ static int be_setup(struct be_adapter *adapter)
        if (status != 0)
                goto rx_qs_destroy;
 
+       status = be_vid_config(adapter);
+       if (status != 0)
+               goto mccqs_destroy;
+
+       status = be_cmd_set_flow_control(adapter, true, true);
+       if (status != 0)
+               goto mccqs_destroy;
        return 0;
 
+mccqs_destroy:
+       be_mcc_queues_destroy(adapter);
 rx_qs_destroy:
        be_rx_queues_destroy(adapter);
 tx_qs_destroy:
index a7e731f8a0da5450f609eb68ccdba5f3acfadec7..69c5b15e22daca1239e5d10bc6f00b767ae3ce4c 100644 (file)
@@ -1093,15 +1093,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
                        return NULL; /* still no slave, return NULL */
        }
 
-       /*
-        * first try the primary link; if arping, a link must tx/rx
-        * traffic before it can be considered the curr_active_slave.
-        * also, we would skip slaves between the curr_active_slave
-        * and primary_slave that may be up and able to arp
-        */
        if ((bond->primary_slave) &&
-           (!bond->params.arp_interval) &&
-           (IS_UP(bond->primary_slave->dev))) {
+           bond->primary_slave->link == BOND_LINK_UP) {
                new_active = bond->primary_slave;
        }
 
@@ -1109,15 +1102,14 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
        old_active = new_active;
 
        bond_for_each_slave_from(bond, new_active, i, old_active) {
-               if (IS_UP(new_active->dev)) {
-                       if (new_active->link == BOND_LINK_UP) {
-                               return new_active;
-                       } else if (new_active->link == BOND_LINK_BACK) {
-                               /* link up, but waiting for stabilization */
-                               if (new_active->delay < mintime) {
-                                       mintime = new_active->delay;
-                                       bestslave = new_active;
-                               }
+               if (new_active->link == BOND_LINK_UP) {
+                       return new_active;
+               } else if (new_active->link == BOND_LINK_BACK &&
+                          IS_UP(new_active->dev)) {
+                       /* link up, but waiting for stabilization */
+                       if (new_active->delay < mintime) {
+                               mintime = new_active->delay;
+                               bestslave = new_active;
                        }
                }
        }
@@ -1211,7 +1203,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
                        write_unlock_bh(&bond->curr_slave_lock);
                        read_unlock(&bond->lock);
 
-                       netdev_bonding_change(bond->dev);
+                       netdev_bonding_change(bond->dev, NETDEV_BONDING_FAILOVER);
 
                        read_lock(&bond->lock);
                        write_lock_bh(&bond->curr_slave_lock);
@@ -1469,14 +1461,17 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
         */
        if (bond->slave_cnt == 0) {
                if (bond_dev->type != slave_dev->type) {
-                       dev_close(bond_dev);
                        pr_debug("%s: change device type from %d to %d\n",
                                bond_dev->name, bond_dev->type, slave_dev->type);
+
+                       netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE);
+
                        if (slave_dev->type != ARPHRD_ETHER)
                                bond_setup_by_slave(bond_dev, slave_dev);
                        else
                                ether_setup(bond_dev);
-                       dev_open(bond_dev);
+
+                       netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE);
                }
        } else if (bond_dev->type != slave_dev->type) {
                pr_err(DRV_NAME ": %s ether type (%d) is different "
@@ -2929,18 +2924,6 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
                }
        }
 
-       read_lock(&bond->curr_slave_lock);
-
-       /*
-        * Trigger a commit if the primary option setting has changed.
-        */
-       if (bond->primary_slave &&
-           (bond->primary_slave != bond->curr_active_slave) &&
-           (bond->primary_slave->link == BOND_LINK_UP))
-               commit++;
-
-       read_unlock(&bond->curr_slave_lock);
-
        return commit;
 }
 
@@ -2961,90 +2944,58 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
                        continue;
 
                case BOND_LINK_UP:
-                       write_lock_bh(&bond->curr_slave_lock);
-
-                       if (!bond->curr_active_slave &&
-                           time_before_eq(jiffies, dev_trans_start(slave->dev) +
-                                          delta_in_ticks)) {
+                       if ((!bond->curr_active_slave &&
+                            time_before_eq(jiffies,
+                                           dev_trans_start(slave->dev) +
+                                           delta_in_ticks)) ||
+                           bond->curr_active_slave != slave) {
                                slave->link = BOND_LINK_UP;
-                               bond_change_active_slave(bond, slave);
                                bond->current_arp_slave = NULL;
 
                                pr_info(DRV_NAME
-                                      ": %s: %s is up and now the "
-                                      "active interface\n",
-                                      bond->dev->name, slave->dev->name);
-
-                       } else if (bond->curr_active_slave != slave) {
-                               /* this slave has just come up but we
-                                * already have a current slave; this can
-                                * also happen if bond_enslave adds a new
-                                * slave that is up while we are searching
-                                * for a new slave
-                                */
-                               slave->link = BOND_LINK_UP;
-                               bond_set_slave_inactive_flags(slave);
-                               bond->current_arp_slave = NULL;
+                                       ": %s: link status definitely "
+                                       "up for interface %s.\n",
+                                       bond->dev->name, slave->dev->name);
 
-                               pr_info(DRV_NAME
-                                      ": %s: backup interface %s is now up\n",
-                                      bond->dev->name, slave->dev->name);
-                       }
+                               if (!bond->curr_active_slave ||
+                                   (slave == bond->primary_slave))
+                                       goto do_failover;
 
-                       write_unlock_bh(&bond->curr_slave_lock);
+                       }
 
-                       break;
+                       continue;
 
                case BOND_LINK_DOWN:
                        if (slave->link_failure_count < UINT_MAX)
                                slave->link_failure_count++;
 
                        slave->link = BOND_LINK_DOWN;
+                       bond_set_slave_inactive_flags(slave);
 
-                       if (slave == bond->curr_active_slave) {
-                               pr_info(DRV_NAME
-                                      ": %s: link status down for active "
-                                      "interface %s, disabling it\n",
-                                      bond->dev->name, slave->dev->name);
-
-                               bond_set_slave_inactive_flags(slave);
-
-                               write_lock_bh(&bond->curr_slave_lock);
-
-                               bond_select_active_slave(bond);
-                               if (bond->curr_active_slave)
-                                       bond->curr_active_slave->jiffies =
-                                               jiffies;
-
-                               write_unlock_bh(&bond->curr_slave_lock);
+                       pr_info(DRV_NAME
+                               ": %s: link status definitely down for "
+                               "interface %s, disabling it\n",
+                               bond->dev->name, slave->dev->name);
 
+                       if (slave == bond->curr_active_slave) {
                                bond->current_arp_slave = NULL;
-
-                       } else if (slave->state == BOND_STATE_BACKUP) {
-                               pr_info(DRV_NAME
-                                      ": %s: backup interface %s is now down\n",
-                                      bond->dev->name, slave->dev->name);
-
-                               bond_set_slave_inactive_flags(slave);
+                               goto do_failover;
                        }
-                       break;
+
+                       continue;
 
                default:
                        pr_err(DRV_NAME
                               ": %s: impossible: new_link %d on slave %s\n",
                               bond->dev->name, slave->new_link,
                               slave->dev->name);
+                       continue;
                }
-       }
 
-       /*
-        * No race with changes to primary via sysfs, as we hold rtnl.
-        */
-       if (bond->primary_slave &&
-           (bond->primary_slave != bond->curr_active_slave) &&
-           (bond->primary_slave->link == BOND_LINK_UP)) {
+do_failover:
+               ASSERT_RTNL();
                write_lock_bh(&bond->curr_slave_lock);
-               bond_change_active_slave(bond, bond->primary_slave);
+               bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
        }
 
index 0900743724624f5e39e8a83622d653a7b29b4d31..df32c109b7acee953f48eef55ddd7b6100cc1e40 100644 (file)
@@ -75,6 +75,13 @@ config CAN_EMS_PCI
          CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
          (http://www.ems-wuensche.de).
 
+config CAN_EMS_USB
+       tristate "EMS CPC-USB/ARM7 CAN/USB interface"
+       depends on USB && CAN_DEV
+       ---help---
+         This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
+         from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
 config CAN_KVASER_PCI
        tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
        depends on PCI && CAN_SJA1000
@@ -82,6 +89,12 @@ config CAN_KVASER_PCI
          This driver is for the the PCIcanx and PCIcan cards (1, 2 or
          4 channel) from Kvaser (http://www.kvaser.com).
 
+config CAN_AT91
+       tristate "Atmel AT91 onchip CAN controller"
+       depends on CAN && CAN_DEV && ARCH_AT91SAM9263
+       ---help---
+         This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+
 config CAN_DEBUG_DEVICES
        bool "CAN devices debugging messages"
        depends on CAN
index 523a941b358b1bd47aaa36888142b25963e7107d..0dea62721f2f52a1f67e4762eb31478b1067542f 100644 (file)
@@ -7,6 +7,9 @@ obj-$(CONFIG_CAN_VCAN)          += vcan.o
 obj-$(CONFIG_CAN_DEV)          += can-dev.o
 can-dev-y                      := dev.o
 
+obj-y                          += usb/
+
 obj-$(CONFIG_CAN_SJA1000)      += sja1000/
+obj-$(CONFIG_CAN_AT91)         += at91_can.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
new file mode 100644 (file)
index 0000000..c3f75ba
--- /dev/null
@@ -0,0 +1,5 @@
+#
+#  Makefile for the Linux Controller Area Network USB drivers.
+#
+
+obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
new file mode 100644 (file)
index 0000000..9012e0a
--- /dev/null
@@ -0,0 +1,1155 @@
+/*
+ * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7
+ *
+ * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+MODULE_AUTHOR("Sebastian Haas <haas@ems-wuensche.com>");
+MODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces");
+MODULE_LICENSE("GPL v2");
+
+/* Control-Values for CPC_Control() Command Subject Selection */
+#define CONTR_CAN_MESSAGE 0x04
+#define CONTR_CAN_STATE   0x0C
+#define CONTR_BUS_ERROR   0x1C
+
+/* Control Command Actions */
+#define CONTR_CONT_OFF 0
+#define CONTR_CONT_ON  1
+#define CONTR_ONCE     2
+
+/* Messages from CPC to PC */
+#define CPC_MSG_TYPE_CAN_FRAME       1  /* CAN data frame */
+#define CPC_MSG_TYPE_RTR_FRAME       8  /* CAN remote frame */
+#define CPC_MSG_TYPE_CAN_PARAMS      12 /* Actual CAN parameters */
+#define CPC_MSG_TYPE_CAN_STATE       14 /* CAN state message */
+#define CPC_MSG_TYPE_EXT_CAN_FRAME   16 /* Extended CAN data frame */
+#define CPC_MSG_TYPE_EXT_RTR_FRAME   17 /* Extended remote frame */
+#define CPC_MSG_TYPE_CONTROL         19 /* change interface behavior */
+#define CPC_MSG_TYPE_CONFIRM         20 /* command processed confirmation */
+#define CPC_MSG_TYPE_OVERRUN         21 /* overrun events */
+#define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */
+#define CPC_MSG_TYPE_ERR_COUNTER     25 /* RX/TX error counter */
+
+/* Messages from the PC to the CPC interface  */
+#define CPC_CMD_TYPE_CAN_FRAME     1   /* CAN data frame */
+#define CPC_CMD_TYPE_CONTROL       3   /* control of interface behavior */
+#define CPC_CMD_TYPE_CAN_PARAMS    6   /* set CAN parameters */
+#define CPC_CMD_TYPE_RTR_FRAME     13  /* CAN remote frame */
+#define CPC_CMD_TYPE_CAN_STATE     14  /* CAN state message */
+#define CPC_CMD_TYPE_EXT_CAN_FRAME 15  /* Extended CAN data frame */
+#define CPC_CMD_TYPE_EXT_RTR_FRAME 16  /* Extended CAN remote frame */
+#define CPC_CMD_TYPE_CAN_EXIT      200 /* exit the CAN */
+
+#define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */
+#define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8  /* clear CPC_MSG queue */
+#define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
+
+#define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */
+
+#define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
+
+/* Overrun types */
+#define CPC_OVR_EVENT_CAN       0x01
+#define CPC_OVR_EVENT_CANSTATE  0x02
+#define CPC_OVR_EVENT_BUSERROR  0x04
+
+/*
+ * If the CAN controller lost a message we indicate it with the highest bit
+ * set in the count field.
+ */
+#define CPC_OVR_HW 0x80
+
+/* Size of the "struct ems_cpc_msg" without the union */
+#define CPC_MSG_HEADER_LEN   11
+#define CPC_CAN_MSG_MIN_SIZE 5
+
+/* Define these values to match your devices */
+#define USB_CPCUSB_VENDOR_ID 0x12D6
+
+#define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
+
+/* Mode register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_MOD_NORMAL 0x00
+#define SJA1000_MOD_RM     0x01
+
+/* ECC register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_ECC_SEG   0x1F
+#define SJA1000_ECC_DIR   0x20
+#define SJA1000_ECC_ERR   0x06
+#define SJA1000_ECC_BIT   0x00
+#define SJA1000_ECC_FORM  0x40
+#define SJA1000_ECC_STUFF 0x80
+#define SJA1000_ECC_MASK  0xc0
+
+/* Status register content */
+#define SJA1000_SR_BS 0x80
+#define SJA1000_SR_ES 0x40
+
+#define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA
+
+/*
+ * The device actually uses a 16MHz clock to generate the CAN clock
+ * but it expects SJA1000 bit settings based on 8MHz (is internally
+ * converted).
+ */
+#define EMS_USB_ARM7_CLOCK 8000000
+
+/*
+ * CAN-Message representation in a CPC_MSG. Message object type is
+ * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
+ * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
+ */
+struct cpc_can_msg {
+       u32 id;
+       u8 length;
+       u8 msg[8];
+};
+
+/* Representation of the CAN parameters for the SJA1000 controller */
+struct cpc_sja1000_params {
+       u8 mode;
+       u8 acc_code0;
+       u8 acc_code1;
+       u8 acc_code2;
+       u8 acc_code3;
+       u8 acc_mask0;
+       u8 acc_mask1;
+       u8 acc_mask2;
+       u8 acc_mask3;
+       u8 btr0;
+       u8 btr1;
+       u8 outp_contr;
+};
+
+/* CAN params message representation */
+struct cpc_can_params {
+       u8 cc_type;
+
+       /* Will support M16C CAN controller in the future */
+       union {
+               struct cpc_sja1000_params sja1000;
+       } cc_params;
+};
+
+/* Structure for confirmed message handling */
+struct cpc_confirm {
+       u8 error; /* error code */
+};
+
+/* Structure for overrun conditions */
+struct cpc_overrun {
+       u8 event;
+       u8 count;
+};
+
+/* SJA1000 CAN errors (compatible to NXP LPC2119) */
+struct cpc_sja1000_can_error {
+       u8 ecc;
+       u8 rxerr;
+       u8 txerr;
+};
+
+/* structure for CAN error conditions */
+struct cpc_can_error {
+       u8 ecode;
+
+       struct {
+               u8 cc_type;
+
+               /* Other controllers may also provide error code capture regs */
+               union {
+                       struct cpc_sja1000_can_error sja1000;
+               } regs;
+       } cc;
+};
+
+/*
+ * Structure containing RX/TX error counter. This structure is used to request
+ * the values of the CAN controllers TX and RX error counter.
+ */
+struct cpc_can_err_counter {
+       u8 rx;
+       u8 tx;
+};
+
+/* Main message type used between library and application */
+struct __attribute__ ((packed)) ems_cpc_msg {
+       u8 type;        /* type of message */
+       u8 length;      /* length of data within union 'msg' */
+       u8 msgid;       /* confirmation handle */
+       u32 ts_sec;     /* timestamp in seconds */
+       u32 ts_nsec;    /* timestamp in nano seconds */
+
+       union {
+               u8 generic[64];
+               struct cpc_can_msg can_msg;
+               struct cpc_can_params can_params;
+               struct cpc_confirm confirmation;
+               struct cpc_overrun overrun;
+               struct cpc_can_error error;
+               struct cpc_can_err_counter err_counter;
+               u8 can_state;
+       } msg;
+};
+
+/*
+ * Table of devices that work with this driver
+ * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet.
+ */
+static struct usb_device_id ems_usb_table[] = {
+       {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)},
+       {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ems_usb_table);
+
+#define RX_BUFFER_SIZE      64
+#define CPC_HEADER_SIZE     4
+#define INTR_IN_BUFFER_SIZE 4
+
+#define MAX_RX_URBS 10
+#define MAX_TX_URBS CAN_ECHO_SKB_MAX
+
+struct ems_usb;
+
+struct ems_tx_urb_context {
+       struct ems_usb *dev;
+
+       u32 echo_index;
+       u8 dlc;
+};
+
+struct ems_usb {
+       struct can_priv can; /* must be the first member */
+       int open_time;
+
+       struct sk_buff *echo_skb[MAX_TX_URBS];
+
+       struct usb_device *udev;
+       struct net_device *netdev;
+
+       atomic_t active_tx_urbs;
+       struct usb_anchor tx_submitted;
+       struct ems_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+       struct usb_anchor rx_submitted;
+
+       struct urb *intr_urb;
+
+       u8 *tx_msg_buffer;
+
+       u8 *intr_in_buffer;
+       unsigned int free_slots; /* remember number of available slots */
+
+       struct ems_cpc_msg active_params; /* active controller parameters */
+};
+
+static void ems_usb_read_interrupt_callback(struct urb *urb)
+{
+       struct ems_usb *dev = urb->context;
+       struct net_device *netdev = dev->netdev;
+       int err;
+
+       if (!netif_device_present(netdev))
+               return;
+
+       switch (urb->status) {
+       case 0:
+               dev->free_slots = dev->intr_in_buffer[1];
+               break;
+
+       case -ECONNRESET: /* unlink */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+
+       default:
+               dev_info(netdev->dev.parent, "Rx interrupt aborted %d\n",
+                        urb->status);
+               break;
+       }
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (err == -ENODEV)
+               netif_device_detach(netdev);
+       else if (err)
+               dev_err(netdev->dev.parent,
+                       "failed resubmitting intr urb: %d\n", err);
+
+       return;
+}
+
+static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       int i;
+       struct net_device_stats *stats = &dev->netdev->stats;
+
+       skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+       if (skb == NULL)
+               return;
+
+       skb->protocol = htons(ETH_P_CAN);
+
+       cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+
+       cf->can_id = msg->msg.can_msg.id;
+       cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8);
+
+       if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME
+           || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
+               cf->can_id |= CAN_EFF_FLAG;
+
+       if (msg->type == CPC_MSG_TYPE_RTR_FRAME
+           || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) {
+               cf->can_id |= CAN_RTR_FLAG;
+       } else {
+               for (i = 0; i < cf->can_dlc; i++)
+                       cf->data[i] = msg->msg.can_msg.msg[i];
+       }
+
+       netif_rx(skb);
+
+       stats->rx_packets++;
+       stats->rx_bytes += cf->can_dlc;
+}
+
+static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       struct net_device_stats *stats = &dev->netdev->stats;
+
+       skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+       if (skb == NULL)
+               return;
+
+       skb->protocol = htons(ETH_P_CAN);
+
+       cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+       memset(cf, 0, sizeof(struct can_frame));
+
+       cf->can_id = CAN_ERR_FLAG;
+       cf->can_dlc = CAN_ERR_DLC;
+
+       if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
+               u8 state = msg->msg.can_state;
+
+               if (state & SJA1000_SR_BS) {
+                       dev->can.state = CAN_STATE_BUS_OFF;
+                       cf->can_id |= CAN_ERR_BUSOFF;
+
+                       can_bus_off(dev->netdev);
+               } else if (state & SJA1000_SR_ES) {
+                       dev->can.state = CAN_STATE_ERROR_WARNING;
+                       dev->can.can_stats.error_warning++;
+               } else {
+                       dev->can.state = CAN_STATE_ERROR_ACTIVE;
+                       dev->can.can_stats.error_passive++;
+               }
+       } else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) {
+               u8 ecc = msg->msg.error.cc.regs.sja1000.ecc;
+               u8 txerr = msg->msg.error.cc.regs.sja1000.txerr;
+               u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr;
+
+               /* bus error interrupt */
+               dev->can.can_stats.bus_error++;
+               stats->rx_errors++;
+
+               cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+               switch (ecc & SJA1000_ECC_MASK) {
+               case SJA1000_ECC_BIT:
+                       cf->data[2] |= CAN_ERR_PROT_BIT;
+                       break;
+               case SJA1000_ECC_FORM:
+                       cf->data[2] |= CAN_ERR_PROT_FORM;
+                       break;
+               case SJA1000_ECC_STUFF:
+                       cf->data[2] |= CAN_ERR_PROT_STUFF;
+                       break;
+               default:
+                       cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+                       cf->data[3] = ecc & SJA1000_ECC_SEG;
+                       break;
+               }
+
+               /* Error occured during transmission? */
+               if ((ecc & SJA1000_ECC_DIR) == 0)
+                       cf->data[2] |= CAN_ERR_PROT_TX;
+
+               if (dev->can.state == CAN_STATE_ERROR_WARNING ||
+                   dev->can.state == CAN_STATE_ERROR_PASSIVE) {
+                       cf->data[1] = (txerr > rxerr) ?
+                           CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
+               }
+       } else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
+               cf->can_id |= CAN_ERR_CRTL;
+               cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+               stats->rx_over_errors++;
+               stats->rx_errors++;
+       }
+
+       netif_rx(skb);
+
+       stats->rx_packets++;
+       stats->rx_bytes += cf->can_dlc;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_read_bulk_callback(struct urb *urb)
+{
+       struct ems_usb *dev = urb->context;
+       struct net_device *netdev;
+       int retval;
+
+       netdev = dev->netdev;
+
+       if (!netif_device_present(netdev))
+               return;
+
+       switch (urb->status) {
+       case 0: /* success */
+               break;
+
+       case -ENOENT:
+               return;
+
+       default:
+               dev_info(netdev->dev.parent, "Rx URB aborted (%d)\n",
+                        urb->status);
+               goto resubmit_urb;
+       }
+
+       if (urb->actual_length > CPC_HEADER_SIZE) {
+               struct ems_cpc_msg *msg;
+               u8 *ibuf = urb->transfer_buffer;
+               u8 msg_count, again, start;
+
+               msg_count = ibuf[0] & ~0x80;
+               again = ibuf[0] & 0x80;
+
+               start = CPC_HEADER_SIZE;
+
+               while (msg_count) {
+                       msg = (struct ems_cpc_msg *)&ibuf[start];
+
+                       switch (msg->type) {
+                       case CPC_MSG_TYPE_CAN_STATE:
+                               /* Process CAN state changes */
+                               ems_usb_rx_err(dev, msg);
+                               break;
+
+                       case CPC_MSG_TYPE_CAN_FRAME:
+                       case CPC_MSG_TYPE_EXT_CAN_FRAME:
+                       case CPC_MSG_TYPE_RTR_FRAME:
+                       case CPC_MSG_TYPE_EXT_RTR_FRAME:
+                               ems_usb_rx_can_msg(dev, msg);
+                               break;
+
+                       case CPC_MSG_TYPE_CAN_FRAME_ERROR:
+                               /* Process errorframe */
+                               ems_usb_rx_err(dev, msg);
+                               break;
+
+                       case CPC_MSG_TYPE_OVERRUN:
+                               /* Message lost while receiving */
+                               ems_usb_rx_err(dev, msg);
+                               break;
+                       }
+
+                       start += CPC_MSG_HEADER_LEN + msg->length;
+                       msg_count--;
+
+                       if (start > urb->transfer_buffer_length) {
+                               dev_err(netdev->dev.parent, "format error\n");
+                               break;
+                       }
+               }
+       }
+
+resubmit_urb:
+       usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+                         urb->transfer_buffer, RX_BUFFER_SIZE,
+                         ems_usb_read_bulk_callback, dev);
+
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (retval == -ENODEV)
+               netif_device_detach(netdev);
+       else if (retval)
+               dev_err(netdev->dev.parent,
+                       "failed resubmitting read bulk urb: %d\n", retval);
+
+       return;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_write_bulk_callback(struct urb *urb)
+{
+       struct ems_tx_urb_context *context = urb->context;
+       struct ems_usb *dev;
+       struct net_device *netdev;
+
+       BUG_ON(!context);
+
+       dev = context->dev;
+       netdev = dev->netdev;
+
+       /* free up our allocated buffer */
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                       urb->transfer_buffer, urb->transfer_dma);
+
+       atomic_dec(&dev->active_tx_urbs);
+
+       if (!netif_device_present(netdev))
+               return;
+
+       if (urb->status)
+               dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n",
+                        urb->status);
+
+       netdev->trans_start = jiffies;
+
+       /* transmission complete interrupt */
+       netdev->stats.tx_packets++;
+       netdev->stats.tx_bytes += context->dlc;
+
+       can_get_echo_skb(netdev, context->echo_index);
+
+       /* Release context */
+       context->echo_index = MAX_TX_URBS;
+
+       if (netif_queue_stopped(netdev))
+               netif_wake_queue(netdev);
+}
+
+/*
+ * Send the given CPC command synchronously
+ */
+static int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+       int actual_length;
+
+       /* Copy payload */
+       memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg,
+              msg->length + CPC_MSG_HEADER_LEN);
+
+       /* Clear header */
+       memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE);
+
+       return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+                           &dev->tx_msg_buffer[0],
+                           msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE,
+                           &actual_length, 1000);
+}
+
+/*
+ * Change CAN controllers' mode register
+ */
+static int ems_usb_write_mode(struct ems_usb *dev, u8 mode)
+{
+       dev->active_params.msg.can_params.cc_params.sja1000.mode = mode;
+
+       return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+/*
+ * Send a CPC_Control command to change behaviour when interface receives a CAN
+ * message, bus error or CAN state changed notifications.
+ */
+static int ems_usb_control_cmd(struct ems_usb *dev, u8 val)
+{
+       struct ems_cpc_msg cmd;
+
+       cmd.type = CPC_CMD_TYPE_CONTROL;
+       cmd.length = CPC_MSG_HEADER_LEN + 1;
+
+       cmd.msgid = 0;
+
+       cmd.msg.generic[0] = val;
+
+       return ems_usb_command_msg(dev, &cmd);
+}
+
+/*
+ * Start interface
+ */
+static int ems_usb_start(struct ems_usb *dev)
+{
+       struct net_device *netdev = dev->netdev;
+       int err, i;
+
+       dev->intr_in_buffer[0] = 0;
+       dev->free_slots = 15; /* initial size */
+
+       for (i = 0; i < MAX_RX_URBS; i++) {
+               struct urb *urb = NULL;
+               u8 *buf = NULL;
+
+               /* create a URB, and a buffer for it */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       dev_err(netdev->dev.parent,
+                               "No memory left for URBs\n");
+                       return -ENOMEM;
+               }
+
+               buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+                                      &urb->transfer_dma);
+               if (!buf) {
+                       dev_err(netdev->dev.parent,
+                               "No memory left for USB buffer\n");
+                       usb_free_urb(urb);
+                       return -ENOMEM;
+               }
+
+               usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+                                 buf, RX_BUFFER_SIZE,
+                                 ems_usb_read_bulk_callback, dev);
+               urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+               usb_anchor_urb(urb, &dev->rx_submitted);
+
+               err = usb_submit_urb(urb, GFP_KERNEL);
+               if (err) {
+                       if (err == -ENODEV)
+                               netif_device_detach(dev->netdev);
+
+                       usb_unanchor_urb(urb);
+                       usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf,
+                                       urb->transfer_dma);
+                       break;
+               }
+
+               /* Drop reference, USB core will take care of freeing it */
+               usb_free_urb(urb);
+       }
+
+       /* Did we submit any URBs */
+       if (i == 0) {
+               dev_warn(netdev->dev.parent, "couldn't setup read URBs\n");
+               return err;
+       }
+
+       /* Warn if we've couldn't transmit all the URBs */
+       if (i < MAX_RX_URBS)
+               dev_warn(netdev->dev.parent, "rx performance may be slow\n");
+
+       /* Setup and start interrupt URB */
+       usb_fill_int_urb(dev->intr_urb, dev->udev,
+                        usb_rcvintpipe(dev->udev, 1),
+                        dev->intr_in_buffer,
+                        INTR_IN_BUFFER_SIZE,
+                        ems_usb_read_interrupt_callback, dev, 1);
+
+       err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
+       if (err) {
+               if (err == -ENODEV)
+                       netif_device_detach(dev->netdev);
+
+               dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",
+                        err);
+
+               return err;
+       }
+
+       /* CPC-USB will transfer received message to host */
+       err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
+       if (err)
+               goto failed;
+
+       /* CPC-USB will transfer CAN state changes to host */
+       err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
+       if (err)
+               goto failed;
+
+       /* CPC-USB will transfer bus errors to host */
+       err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
+       if (err)
+               goto failed;
+
+       err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
+       if (err)
+               goto failed;
+
+       dev->can.state = CAN_STATE_ERROR_ACTIVE;
+
+       return 0;
+
+failed:
+       if (err == -ENODEV)
+               netif_device_detach(dev->netdev);
+
+       dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);
+
+       return err;
+}
+
+static void unlink_all_urbs(struct ems_usb *dev)
+{
+       int i;
+
+       usb_unlink_urb(dev->intr_urb);
+
+       usb_kill_anchored_urbs(&dev->rx_submitted);
+
+       usb_kill_anchored_urbs(&dev->tx_submitted);
+       atomic_set(&dev->active_tx_urbs, 0);
+
+       for (i = 0; i < MAX_TX_URBS; i++)
+               dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static int ems_usb_open(struct net_device *netdev)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+       int err;
+
+       err = ems_usb_write_mode(dev, SJA1000_MOD_RM);
+       if (err)
+               return err;
+
+       /* common open */
+       err = open_candev(netdev);
+       if (err)
+               return err;
+
+       /* finally start device */
+       err = ems_usb_start(dev);
+       if (err) {
+               if (err == -ENODEV)
+                       netif_device_detach(dev->netdev);
+
+               dev_warn(netdev->dev.parent, "couldn't start device: %d\n",
+                        err);
+
+               close_candev(netdev);
+
+               return err;
+       }
+
+       dev->open_time = jiffies;
+
+       netif_start_queue(netdev);
+
+       return 0;
+}
+
+static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+       struct ems_tx_urb_context *context = NULL;
+       struct net_device_stats *stats = &netdev->stats;
+       struct can_frame *cf = (struct can_frame *)skb->data;
+       struct ems_cpc_msg *msg;
+       struct urb *urb;
+       u8 *buf;
+       int i, err;
+       size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
+                       + sizeof(struct cpc_can_msg);
+
+       /* create a URB, and a buffer for it, and copy the data to the URB */
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(netdev->dev.parent, "No memory left for URBs\n");
+               goto nomem;
+       }
+
+       buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
+       if (!buf) {
+               dev_err(netdev->dev.parent, "No memory left for USB buffer\n");
+               usb_free_urb(urb);
+               goto nomem;
+       }
+
+       msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
+
+       msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK;
+       msg->msg.can_msg.length = cf->can_dlc;
+
+       if (cf->can_id & CAN_RTR_FLAG) {
+               msg->type = cf->can_id & CAN_EFF_FLAG ?
+                       CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;
+
+               msg->length = CPC_CAN_MSG_MIN_SIZE;
+       } else {
+               msg->type = cf->can_id & CAN_EFF_FLAG ?
+                       CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;
+
+               for (i = 0; i < cf->can_dlc; i++)
+                       msg->msg.can_msg.msg[i] = cf->data[i];
+
+               msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc;
+       }
+
+       for (i = 0; i < MAX_TX_URBS; i++) {
+               if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
+                       context = &dev->tx_contexts[i];
+                       break;
+               }
+       }
+
+       /*
+        * May never happen! When this happens we'd more URBs in flight as
+        * allowed (MAX_TX_URBS).
+        */
+       if (!context) {
+               usb_unanchor_urb(urb);
+               usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+
+               dev_warn(netdev->dev.parent, "couldn't find free context\n");
+
+               return NETDEV_TX_BUSY;
+       }
+
+       context->dev = dev;
+       context->echo_index = i;
+       context->dlc = cf->can_dlc;
+
+       usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
+                         size, ems_usb_write_bulk_callback, context);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       usb_anchor_urb(urb, &dev->tx_submitted);
+
+       can_put_echo_skb(skb, netdev, context->echo_index);
+
+       atomic_inc(&dev->active_tx_urbs);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (unlikely(err)) {
+               can_free_echo_skb(netdev, context->echo_index);
+
+               usb_unanchor_urb(urb);
+               usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+               dev_kfree_skb(skb);
+
+               atomic_dec(&dev->active_tx_urbs);
+
+               if (err == -ENODEV) {
+                       netif_device_detach(netdev);
+               } else {
+                       dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err);
+
+                       stats->tx_dropped++;
+               }
+       } else {
+               netdev->trans_start = jiffies;
+
+               /* Slow down tx path */
+               if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
+                   dev->free_slots < 5) {
+                       netif_stop_queue(netdev);
+               }
+       }
+
+       /*
+        * Release our reference to this URB, the USB core will eventually free
+        * it entirely.
+        */
+       usb_free_urb(urb);
+
+       return NETDEV_TX_OK;
+
+nomem:
+       if (skb)
+               dev_kfree_skb(skb);
+
+       stats->tx_dropped++;
+
+       return NETDEV_TX_OK;
+}
+
+static int ems_usb_close(struct net_device *netdev)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+
+       /* Stop polling */
+       unlink_all_urbs(dev);
+
+       netif_stop_queue(netdev);
+
+       /* Set CAN controller to reset mode */
+       if (ems_usb_write_mode(dev, SJA1000_MOD_RM))
+               dev_warn(netdev->dev.parent, "couldn't stop device");
+
+       close_candev(netdev);
+
+       dev->open_time = 0;
+
+       return 0;
+}
+
+static const struct net_device_ops ems_usb_netdev_ops = {
+       .ndo_open = ems_usb_open,
+       .ndo_stop = ems_usb_close,
+       .ndo_start_xmit = ems_usb_start_xmit,
+};
+
+static struct can_bittiming_const ems_usb_bittiming_const = {
+       .name = "ems_usb",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 64,
+       .brp_inc = 1,
+};
+
+static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+
+       if (!dev->open_time)
+               return -EINVAL;
+
+       switch (mode) {
+       case CAN_MODE_START:
+               if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
+                       dev_warn(netdev->dev.parent, "couldn't start device");
+
+               if (netif_queue_stopped(netdev))
+                       netif_wake_queue(netdev);
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int ems_usb_set_bittiming(struct net_device *netdev)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+       struct can_bittiming *bt = &dev->can.bittiming;
+       u8 btr0, btr1;
+
+       btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+       btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+               (((bt->phase_seg2 - 1) & 0x7) << 4);
+       if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+               btr1 |= 0x80;
+
+       dev_info(netdev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
+                btr0, btr1);
+
+       dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0;
+       dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1;
+
+       return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+static void init_params_sja1000(struct ems_cpc_msg *msg)
+{
+       struct cpc_sja1000_params *sja1000 =
+               &msg->msg.can_params.cc_params.sja1000;
+
+       msg->type = CPC_CMD_TYPE_CAN_PARAMS;
+       msg->length = sizeof(struct cpc_can_params);
+       msg->msgid = 0;
+
+       msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000;
+
+       /* Acceptance filter open */
+       sja1000->acc_code0 = 0x00;
+       sja1000->acc_code1 = 0x00;
+       sja1000->acc_code2 = 0x00;
+       sja1000->acc_code3 = 0x00;
+
+       /* Acceptance filter open */
+       sja1000->acc_mask0 = 0xFF;
+       sja1000->acc_mask1 = 0xFF;
+       sja1000->acc_mask2 = 0xFF;
+       sja1000->acc_mask3 = 0xFF;
+
+       sja1000->btr0 = 0;
+       sja1000->btr1 = 0;
+
+       sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL;
+       sja1000->mode = SJA1000_MOD_RM;
+}
+
+/*
+ * probe function for new CPC-USB devices
+ */
+static int ems_usb_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       struct net_device *netdev;
+       struct ems_usb *dev;
+       int i, err = -ENOMEM;
+
+       netdev = alloc_candev(sizeof(struct ems_usb));
+       if (!netdev) {
+               dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
+               return -ENOMEM;
+       }
+
+       dev = netdev_priv(netdev);
+
+       dev->udev = interface_to_usbdev(intf);
+       dev->netdev = netdev;
+
+       dev->can.state = CAN_STATE_STOPPED;
+       dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
+       dev->can.bittiming_const = &ems_usb_bittiming_const;
+       dev->can.do_set_bittiming = ems_usb_set_bittiming;
+       dev->can.do_set_mode = ems_usb_set_mode;
+
+       netdev->flags |= IFF_ECHO; /* we support local echo */
+
+       netdev->netdev_ops = &ems_usb_netdev_ops;
+
+       netdev->flags |= IFF_ECHO; /* we support local echo */
+
+       init_usb_anchor(&dev->rx_submitted);
+
+       init_usb_anchor(&dev->tx_submitted);
+       atomic_set(&dev->active_tx_urbs, 0);
+
+       for (i = 0; i < MAX_TX_URBS; i++)
+               dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+       dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->intr_urb) {
+               dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n");
+               goto cleanup_candev;
+       }
+
+       dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
+       if (!dev->intr_in_buffer) {
+               dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n");
+               goto cleanup_intr_urb;
+       }
+
+       dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
+                                    sizeof(struct ems_cpc_msg), GFP_KERNEL);
+       if (!dev->tx_msg_buffer) {
+               dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n");
+               goto cleanup_intr_in_buffer;
+       }
+
+       usb_set_intfdata(intf, dev);
+
+       SET_NETDEV_DEV(netdev, &intf->dev);
+
+       init_params_sja1000(&dev->active_params);
+
+       err = ems_usb_command_msg(dev, &dev->active_params);
+       if (err) {
+               dev_err(netdev->dev.parent,
+                       "couldn't initialize controller: %d\n", err);
+               goto cleanup_tx_msg_buffer;
+       }
+
+       err = register_candev(netdev);
+       if (err) {
+               dev_err(netdev->dev.parent,
+                       "couldn't register CAN device: %d\n", err);
+               goto cleanup_tx_msg_buffer;
+       }
+
+       return 0;
+
+cleanup_tx_msg_buffer:
+       kfree(dev->tx_msg_buffer);
+
+cleanup_intr_in_buffer:
+       kfree(dev->intr_in_buffer);
+
+cleanup_intr_urb:
+       usb_free_urb(dev->intr_urb);
+
+cleanup_candev:
+       free_candev(netdev);
+
+       return err;
+}
+
+/*
+ * called by the usb core when the device is removed from the system
+ */
+static void ems_usb_disconnect(struct usb_interface *intf)
+{
+       struct ems_usb *dev = usb_get_intfdata(intf);
+
+       usb_set_intfdata(intf, NULL);
+
+       if (dev) {
+               unregister_netdev(dev->netdev);
+               free_candev(dev->netdev);
+
+               unlink_all_urbs(dev);
+
+               usb_free_urb(dev->intr_urb);
+
+               kfree(dev->intr_in_buffer);
+       }
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver ems_usb_driver = {
+       .name = "ems_usb",
+       .probe = ems_usb_probe,
+       .disconnect = ems_usb_disconnect,
+       .id_table = ems_usb_table,
+};
+
+static int __init ems_usb_init(void)
+{
+       int err;
+
+       printk(KERN_INFO "CPC-USB kernel driver loaded\n");
+
+       /* register this driver with the USB subsystem */
+       err = usb_register(&ems_usb_driver);
+
+       if (err) {
+               err("usb_register failed. Error number %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void __exit ems_usb_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&ems_usb_driver);
+}
+
+module_init(ems_usb_init);
+module_exit(ems_usb_exit);
index 6971f6cd37fa3be0395b360ab0e086f8c25a2ae7..80ac56313981983063340adb95150fe40d76bea9 100644 (file)
@@ -80,7 +80,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
        skb->dev       = dev;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-       netif_rx(skb);
+       netif_rx_ni(skb);
 }
 
 static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
index d45eacb76702a5134aea3fc50138af013cb95e29..211c8e9182fc51566fffac1fff201da34bc8ee05 100644 (file)
@@ -85,8 +85,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
 
        cp->uio_dev = iminor(inode);
 
-       cnic_shutdown_bnx2_rx_ring(dev);
-
        cnic_init_bnx2_tx_ring(dev);
        cnic_init_bnx2_rx_ring(dev);
 
@@ -98,6 +96,8 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
        struct cnic_dev *dev = uinfo->priv;
        struct cnic_local *cp = dev->cnic_priv;
 
+       cnic_shutdown_bnx2_rx_ring(dev);
+
        cp->uio_dev = -1;
        return 0;
 }
index 3e3fab8afb1ee37118a040d68e757603235d14e1..61f9da2b49431d88056daa1bbcb4b6bceaee86b7 100644 (file)
@@ -1109,7 +1109,7 @@ static int external_switch;
 static int __devinit cpmac_probe(struct platform_device *pdev)
 {
        int rc, phy_id;
-       char mdio_bus_id[BUS_ID_SIZE];
+       char mdio_bus_id[MII_BUS_ID_SIZE];
        struct resource *mem;
        struct cpmac_priv *priv;
        struct net_device *dev;
@@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
        pdata = pdev->dev.platform_data;
 
        if (external_switch || dumb_switch) {
-               strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
+               strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
                phy_id = pdev->id;
        } else {
                for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
                                continue;
                        if (!cpmac_mii->phy_map[phy_id])
                                continue;
-                       strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
+                       strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
                        break;
                }
        }
@@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
        priv->msg_enable = netif_msg_init(debug_level, 0xff);
        memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
 
-       snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+       snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
 
        priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
                                                PHY_INTERFACE_MODE_MII);
index 977c3d358279378086f2e82ee03ed21f31221dc7..41bd7aeafd8248119b21fe13e6e7576012e6bd29 100644 (file)
@@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_poll_controller    = ehea_netpoll,
 #endif
        .ndo_get_stats          = ehea_get_stats,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = ehea_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_multicast_list = ehea_set_multicast_list,
index 6158c0f3b2051f4768649a3d09fed9ebc017bb30..f8f5772557cefa661d864d0e0dfa1fde6c467ac0 100644 (file)
@@ -49,11 +49,10 @@ static s32  igb_read_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16 *);
 static s32  igb_reset_hw_82575(struct e1000_hw *);
 static s32  igb_set_d0_lplu_state_82575(struct e1000_hw *, bool);
 static s32  igb_setup_copper_link_82575(struct e1000_hw *);
-static s32  igb_setup_fiber_serdes_link_82575(struct e1000_hw *);
+static s32  igb_setup_serdes_link_82575(struct e1000_hw *);
 static s32  igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16);
 static void igb_clear_hw_cntrs_82575(struct e1000_hw *);
 static s32  igb_acquire_swfw_sync_82575(struct e1000_hw *, u16);
-static void igb_configure_pcs_link_82575(struct e1000_hw *);
 static s32  igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *, u16 *,
                                                 u16 *);
 static s32  igb_get_phy_id_82575(struct e1000_hw *);
@@ -105,16 +104,20 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
        dev_spec->sgmii_active = false;
 
        ctrl_ext = rd32(E1000_CTRL_EXT);
-       if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) ==
-           E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES) {
-               hw->phy.media_type = e1000_media_type_internal_serdes;
-               ctrl_ext |= E1000_CTRL_I2C_ENA;
-       } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) {
+       switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
+       case E1000_CTRL_EXT_LINK_MODE_SGMII:
                dev_spec->sgmii_active = true;
                ctrl_ext |= E1000_CTRL_I2C_ENA;
-       } else {
+               break;
+       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
+               hw->phy.media_type = e1000_media_type_internal_serdes;
+               ctrl_ext |= E1000_CTRL_I2C_ENA;
+               break;
+       default:
                ctrl_ext &= ~E1000_CTRL_I2C_ENA;
+               break;
        }
+
        wr32(E1000_CTRL_EXT, ctrl_ext);
 
        /* Set mta register count */
@@ -134,7 +137,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
        mac->ops.setup_physical_interface =
                (hw->phy.media_type == e1000_media_type_copper)
                        ? igb_setup_copper_link_82575
-                       : igb_setup_fiber_serdes_link_82575;
+                       : igb_setup_serdes_link_82575;
 
        /* NVM initialization */
        eecd = rd32(E1000_EECD);
@@ -379,6 +382,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32  ret_val = 0;
        u16 phy_id;
+       u32 ctrl_ext;
 
        /*
         * For SGMII PHYs, we try the list of possible addresses until
@@ -393,6 +397,12 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
                goto out;
        }
 
+       /* Power on sgmii phy if it is disabled */
+       ctrl_ext = rd32(E1000_CTRL_EXT);
+       wr32(E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
+       wrfl();
+       msleep(300);
+
        /*
         * The address field in the I2CCMD register is 3 bits and 0 is invalid.
         * Therefore, we need to test 1-7
@@ -418,9 +428,12 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
                phy->addr = 0;
                ret_val = -E1000_ERR_PHY;
                goto out;
+       } else {
+               ret_val = igb_get_phy_id(hw);
        }
 
-       ret_val = igb_get_phy_id(hw);
+       /* restore previous sfp cage power state */
+       wr32(E1000_CTRL_EXT, ctrl_ext);
 
 out:
        return ret_val;
@@ -766,17 +779,18 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed,
 }
 
 /**
- *  igb_shutdown_fiber_serdes_link_82575 - Remove link during power down
+ *  igb_shutdown_serdes_link_82575 - Remove link during power down
  *  @hw: pointer to the HW structure
  *
  *  In the case of fiber serdes, shut down optics and PCS on driver unload
  *  when management pass thru is not enabled.
  **/
-void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
+void igb_shutdown_serdes_link_82575(struct e1000_hw *hw)
 {
        u32 reg;
 
-       if (hw->phy.media_type != e1000_media_type_internal_serdes)
+       if (hw->phy.media_type != e1000_media_type_internal_serdes ||
+           igb_sgmii_active_82575(hw))
                return;
 
        /* if the management interface is not enabled, then power down */
@@ -788,7 +802,7 @@ void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
 
                /* shutdown the laser */
                reg = rd32(E1000_CTRL_EXT);
-               reg |= E1000_CTRL_EXT_SDP7_DATA;
+               reg |= E1000_CTRL_EXT_SDP3_DATA;
                wr32(E1000_CTRL_EXT, reg);
 
                /* flush the write to verify completion */
@@ -927,6 +941,17 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        wr32(E1000_CTRL, ctrl);
 
+       ret_val = igb_setup_serdes_link_82575(hw);
+       if (ret_val)
+               goto out;
+
+       if (igb_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
+               ret_val = hw->phy.ops.reset(hw);
+               if (ret_val) {
+                       hw_dbg("Error resetting the PHY.\n");
+                       goto out;
+               }
+       }
        switch (hw->phy.type) {
        case e1000_phy_m88:
                ret_val = igb_copper_link_setup_m88(hw);
@@ -963,8 +988,6 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
                }
        }
 
-       igb_configure_pcs_link_82575(hw);
-
        /*
         * Check link status. Wait up to 100 microseconds for link to become
         * valid.
@@ -987,14 +1010,18 @@ out:
 }
 
 /**
- *  igb_setup_fiber_serdes_link_82575 - Setup link for fiber/serdes
+ *  igb_setup_serdes_link_82575 - Setup link for fiber/serdes
  *  @hw: pointer to the HW structure
  *
  *  Configures speed and duplex for fiber and serdes links.
  **/
-static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
+static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 {
-       u32 reg;
+       u32 ctrl_reg, reg;
+
+       if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
+           !igb_sgmii_active_82575(hw))
+               return 0;
 
        /*
         * On the 82575, SerDes loopback mode persists until it is
@@ -1004,26 +1031,38 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
         */
        wr32(E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
 
-       /* Force link up, set 1gb, set both sw defined pins */
-       reg = rd32(E1000_CTRL);
-       reg |= E1000_CTRL_SLU |
-              E1000_CTRL_SPD_1000 |
-              E1000_CTRL_FRCSPD |
-              E1000_CTRL_SWDPIN0 |
-              E1000_CTRL_SWDPIN1;
-       wr32(E1000_CTRL, reg);
-
-       /* Power on phy for 82576 fiber adapters */
-       if (hw->mac.type == e1000_82576) {
-               reg = rd32(E1000_CTRL_EXT);
-               reg &= ~E1000_CTRL_EXT_SDP7_DATA;
-               wr32(E1000_CTRL_EXT, reg);
+       /* power on the sfp cage if present */
+       reg = rd32(E1000_CTRL_EXT);
+       reg &= ~E1000_CTRL_EXT_SDP3_DATA;
+       wr32(E1000_CTRL_EXT, reg);
+
+       ctrl_reg = rd32(E1000_CTRL);
+       ctrl_reg |= E1000_CTRL_SLU;
+
+       if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) {
+               /* set both sw defined pins */
+               ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
+
+               /* Set switch control to serdes energy detect */
+               reg = rd32(E1000_CONNSW);
+               reg |= E1000_CONNSW_ENRGSRC;
+               wr32(E1000_CONNSW, reg);
+       }
+
+       reg = rd32(E1000_PCS_LCTL);
+
+       if (igb_sgmii_active_82575(hw)) {
+               /* allow time for SFP cage to power up phy */
+               msleep(300);
+
+               /* AN time out should be disabled for SGMII mode */
+               reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
+       } else {
+               ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
+                           E1000_CTRL_FD | E1000_CTRL_FRCDPX;
        }
 
-       /* Set switch control to serdes energy detect */
-       reg = rd32(E1000_CONNSW);
-       reg |= E1000_CONNSW_ENRGSRC;
-       wr32(E1000_CONNSW, reg);
+       wr32(E1000_CTRL, ctrl_reg);
 
        /*
         * New SerDes mode allows for forcing speed or autonegotiating speed
@@ -1031,12 +1070,21 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
         * mode that will be compatible with older link partners and switches.
         * However, both are supported by the hardware and some drivers/tools.
         */
-       reg = rd32(E1000_PCS_LCTL);
 
        reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
                E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
 
-       if (hw->mac.autoneg) {
+       /*
+        * We force flow control to prevent the CTRL register values from being
+        * overwritten by the autonegotiated flow control values
+        */
+       reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+
+       /*
+        * we always set sgmii to autoneg since it is the phy that will be
+        * forcing the link and the serdes is just a go-between
+        */
+       if (hw->mac.autoneg || igb_sgmii_active_82575(hw)) {
                /* Set PCS register for autoneg */
                reg |= E1000_PCS_LCTL_FSV_1000 |      /* Force 1000    */
                       E1000_PCS_LCTL_FDV_FULL |      /* SerDes Full duplex */
@@ -1053,75 +1101,12 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
                hw_dbg("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg);
        }
 
-       if (hw->mac.type == e1000_82576) {
-               reg |= E1000_PCS_LCTL_FORCE_FCTRL;
-               igb_force_mac_fc(hw);
-       }
-
        wr32(E1000_PCS_LCTL, reg);
 
-       return 0;
-}
-
-/**
- *  igb_configure_pcs_link_82575 - Configure PCS link
- *  @hw: pointer to the HW structure
- *
- *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
- *  only used on copper connections where the serialized gigabit media
- *  independent interface (sgmii) is being used.  Configures the link
- *  for auto-negotiation or forces speed/duplex.
- **/
-static void igb_configure_pcs_link_82575(struct e1000_hw *hw)
-{
-       struct e1000_mac_info *mac = &hw->mac;
-       u32 reg = 0;
-
-       if (hw->phy.media_type != e1000_media_type_copper ||
-           !(igb_sgmii_active_82575(hw)))
-               return;
-
-       /* For SGMII, we need to issue a PCS autoneg restart */
-       reg = rd32(E1000_PCS_LCTL);
-
-       /* AN time out should be disabled for SGMII mode */
-       reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
-
-       if (mac->autoneg) {
-               /* Make sure forced speed and force link are not set */
-               reg &= ~(E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
-
-               /*
-                * The PHY should be setup prior to calling this function.
-                * All we need to do is restart autoneg and enable autoneg.
-                */
-               reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE;
-       } else {
-               /* Set PCS register for forced speed */
-
-               /* Turn off bits for full duplex, speed, and autoneg */
-               reg &= ~(E1000_PCS_LCTL_FSV_1000 |
-                        E1000_PCS_LCTL_FSV_100 |
-                        E1000_PCS_LCTL_FDV_FULL |
-                        E1000_PCS_LCTL_AN_ENABLE);
-
-               /* Check for duplex first */
-               if (mac->forced_speed_duplex & E1000_ALL_FULL_DUPLEX)
-                       reg |= E1000_PCS_LCTL_FDV_FULL;
-
-               /* Now set speed */
-               if (mac->forced_speed_duplex & E1000_ALL_100_SPEED)
-                       reg |= E1000_PCS_LCTL_FSV_100;
-
-               /* Force speed and force link */
-               reg |= E1000_PCS_LCTL_FSD |
-                      E1000_PCS_LCTL_FORCE_LINK |
-                      E1000_PCS_LCTL_FLV_LINK_UP;
+       if (!igb_sgmii_active_82575(hw))
+               igb_force_mac_fc(hw);
 
-               hw_dbg("Wrote 0x%08X to PCS_LCTL to configure forced link\n",
-                      reg);
-       }
-       wr32(E1000_PCS_LCTL, reg);
+       return 0;
 }
 
 /**
@@ -1248,7 +1233,8 @@ static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw)
        temp = rd32(E1000_LENERRS);
 
        /* This register should not be read in copper configurations */
-       if (hw->phy.media_type == e1000_media_type_internal_serdes)
+       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+           igb_sgmii_active_82575(hw))
                temp = rd32(E1000_SCVPC);
 }
 
index 8a1e6597061f5463464078fd6a52c7f6c1cafe83..ebd146fd4e15dc975e05652134a36167b7ac94ee 100644 (file)
@@ -28,7 +28,7 @@
 #ifndef _E1000_82575_H_
 #define _E1000_82575_H_
 
-extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
+extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
 extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
 
 #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
index c85829355d508c9917b84adedc4360b1af694f19..cb916833f303126beb0b35c4584ae91d0949be3c 100644 (file)
@@ -44,7 +44,7 @@
 #define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
 
 /* Extended Device Control */
-#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Defineable Pin 3 */
 /* Physical Func Reset Done Indication */
 #define E1000_CTRL_EXT_PFRSTD    0x00004000
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
index a0231cd079f128666c74d95f21ec790145d3786e..7d76bb085e105923080bb8304209f0874c5eeff6 100644 (file)
@@ -285,41 +285,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
        wrfl();
 }
 
-/**
- *  igb_update_mc_addr_list - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates entire Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void igb_update_mc_addr_list(struct e1000_hw *hw,
-                             u8 *mc_addr_list, u32 mc_addr_count)
-{
-       u32 hash_value, hash_bit, hash_reg;
-       int i;
-
-       /* clear mta_shadow */
-       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
-       /* update mta_shadow from mc_addr_list */
-       for (i = 0; (u32) i < mc_addr_count; i++) {
-               hash_value = igb_hash_mc_addr(hw, mc_addr_list);
-
-               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-               hash_bit = hash_value & 0x1F;
-
-               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
-               mc_addr_list += (ETH_ALEN);
-       }
-
-       /* replace the entire MTA table */
-       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
-               array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
-       wrfl();
-}
-
 /**
  *  igb_hash_mc_addr - Generate a multicast hash value
  *  @hw: pointer to the HW structure
@@ -329,7 +294,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
  *  the multicast filter table array address and new table value.  See
  *  igb_mta_set()
  **/
-u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
        u32 hash_value, hash_mask;
        u8 bit_shift = 0;
@@ -391,6 +356,41 @@ u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
        return hash_value;
 }
 
+/**
+ *  igb_update_mc_addr_list - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void igb_update_mc_addr_list(struct e1000_hw *hw,
+                             u8 *mc_addr_list, u32 mc_addr_count)
+{
+       u32 hash_value, hash_bit, hash_reg;
+       int i;
+
+       /* clear mta_shadow */
+       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+       /* update mta_shadow from mc_addr_list */
+       for (i = 0; (u32) i < mc_addr_count; i++) {
+               hash_value = igb_hash_mc_addr(hw, mc_addr_list);
+
+               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+               hash_bit = hash_value & 0x1F;
+
+               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+               mc_addr_list += (ETH_ALEN);
+       }
+
+       /* replace the entire MTA table */
+       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+               array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
+       wrfl();
+}
+
 /**
  *  igb_clear_hw_cntrs_base - Clear base hardware counters
  *  @hw: pointer to the HW structure
index 7518af8cbbf5ef68820e6b7dac63385ba8234212..bca17d88241731c344a3e3a9f1fc49f1d6069def 100644 (file)
@@ -88,6 +88,5 @@ enum e1000_mng_mode {
 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN    0x2
 
 extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
-extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
 
 #endif
index c1f4da630420f186dfbff445c65bd943b95a1738..ee460600e74b42d814722f949c659e08eb20752f 100644 (file)
@@ -1565,9 +1565,12 @@ out:
  **/
 s32 igb_phy_sw_reset(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = 0;
        u16 phy_ctrl;
 
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
        ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
        if (ret_val)
                goto out;
index 943186b78483f27d9f7fb6d761ea0f5f60158d07..d2639c4a086dfc0ed7f265c472b9df1c1edcb1db 100644 (file)
@@ -5320,7 +5320,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
 
        *enable_wake = wufc || adapter->en_mng_pt;
        if (!*enable_wake)
-               igb_shutdown_fiber_serdes_link_82575(hw);
+               igb_shutdown_serdes_link_82575(hw);
 
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant. */
index dd688d45e9cdaeb35dfb6a9ea6479d3fa1b40f76..385be6016667a6fd1049538443d634627f32db03 100644 (file)
@@ -267,7 +267,8 @@ struct ixgbe_adapter {
        enum ixgbe_fc_mode last_lfc_mode;
 
        /* Interrupt Throttle Rate */
-       u32 itr_setting;
+       u32 rx_itr_setting;
+       u32 tx_itr_setting;
        u16 eitr_low;
        u16 eitr_high;
 
@@ -351,7 +352,8 @@ struct ixgbe_adapter {
        struct ixgbe_hw_stats stats;
 
        /* Interrupt Throttle Rate */
-       u32 eitr_param;
+       u32 rx_eitr_param;
+       u32 tx_eitr_param;
 
        unsigned long state;
        u64 tx_busy;
index cb7f0c3c6e16ea40c2c1e2816d62635fb0cee305..56b12f3192f1d5b18d72b77bb03aab9807708b5f 100644 (file)
@@ -322,14 +322,16 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
                break;
        case IXGBE_DEV_ID_82598AF_DUAL_PORT:
        case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
-       case IXGBE_DEV_ID_82598EB_CX4:
-       case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
        case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
        case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
        case IXGBE_DEV_ID_82598EB_XF_LR:
        case IXGBE_DEV_ID_82598EB_SFP_LOM:
                media_type = ixgbe_media_type_fiber;
                break;
+       case IXGBE_DEV_ID_82598EB_CX4:
+       case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
+               media_type = ixgbe_media_type_cx4;
+               break;
        case IXGBE_DEV_ID_82598AT:
        case IXGBE_DEV_ID_82598AT2:
                media_type = ixgbe_media_type_copper;
index 61af47e75aa1c66670f284133a5351d99c69ad4b..2ec58dcdb82bf6fba6013599c7695eb76d0804bc 100644 (file)
@@ -337,6 +337,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
        case IXGBE_DEV_ID_82599_SFP:
                media_type = ixgbe_media_type_fiber;
                break;
+       case IXGBE_DEV_ID_82599_CX4:
+               media_type = ixgbe_media_type_cx4;
+               break;
        default:
                media_type = ixgbe_media_type_unknown;
                break;
index 026e94a9984954d1b2815aaacca9aadf7f854584..53b0a6680254fdbd816692f0a88e1616f312a7aa 100644 (file)
@@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
        ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
 
        /* only valid if in constant ITR mode */
-       switch (adapter->itr_setting) {
+       switch (adapter->rx_itr_setting) {
        case 0:
                /* throttling disabled */
                ec->rx_coalesce_usecs = 0;
@@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
                break;
        default:
                /* fixed interrupt rate mode */
-               ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
+               ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
                break;
        }
+
+       /* only valid if in constant ITR mode */
+       switch (adapter->tx_itr_setting) {
+       case 0:
+               /* throttling disabled */
+               ec->tx_coalesce_usecs = 0;
+               break;
+       case 1:
+               /* dynamic ITR mode */
+               ec->tx_coalesce_usecs = 1;
+               break;
+       default:
+               ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
+               break;
+       }
+
        return 0;
 }
 
@@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
        struct ixgbe_q_vector *q_vector;
        int i;
 
+       /*
+        * don't accept tx specific changes if we've got mixed RxTx vectors
+        * test and jump out here if needed before changing the rx numbers
+        */
+       if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
+           adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+               return -EINVAL;
+
        if (ec->tx_max_coalesced_frames_irq)
                adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
 
@@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                        return -EINVAL;
 
                /* store the value in ints/second */
-               adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
+               adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
                /* static value of interrupt rate */
-               adapter->itr_setting = adapter->eitr_param;
+               adapter->rx_itr_setting = adapter->rx_eitr_param;
                /* clear the lower bit as its used for dynamic state */
-               adapter->itr_setting &= ~1;
+               adapter->rx_itr_setting &= ~1;
        } else if (ec->rx_coalesce_usecs == 1) {
                /* 1 means dynamic mode */
-               adapter->eitr_param = 20000;
-               adapter->itr_setting = 1;
+               adapter->rx_eitr_param = 20000;
+               adapter->rx_itr_setting = 1;
        } else {
                /*
                 * any other value means disable eitr, which is best
                 * served by setting the interrupt rate very high
                 */
                if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
-                       adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
+                       adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
                else
-                       adapter->eitr_param = IXGBE_MAX_INT_RATE;
-               adapter->itr_setting = 0;
+                       adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
+               adapter->rx_itr_setting = 0;
+       }
+
+       if (ec->tx_coalesce_usecs > 1) {
+               /* check the limits */
+               if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
+                   (1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
+                       return -EINVAL;
+
+               /* store the value in ints/second */
+               adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
+
+               /* static value of interrupt rate */
+               adapter->tx_itr_setting = adapter->tx_eitr_param;
+
+               /* clear the lower bit as its used for dynamic state */
+               adapter->tx_itr_setting &= ~1;
+       } else if (ec->tx_coalesce_usecs == 1) {
+               /* 1 means dynamic mode */
+               adapter->tx_eitr_param = 10000;
+               adapter->tx_itr_setting = 1;
+       } else {
+               adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
+               adapter->tx_itr_setting = 0;
        }
 
        /* MSI/MSIx Interrupt Mode */
@@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                for (i = 0; i < num_vectors; i++) {
                        q_vector = adapter->q_vector[i];
                        if (q_vector->txr_count && !q_vector->rxr_count)
-                               /* tx vector gets half the rate */
-                               q_vector->eitr = (adapter->eitr_param >> 1);
+                               /* tx only */
+                               q_vector->eitr = adapter->tx_eitr_param;
                        else
                                /* rx only or mixed */
-                               q_vector->eitr = adapter->eitr_param;
+                               q_vector->eitr = adapter->rx_eitr_param;
                        ixgbe_write_eitr(q_vector);
                }
        /* Legacy Interrupt Mode */
        } else {
                q_vector = adapter->q_vector[0];
-               q_vector->eitr = adapter->eitr_param;
+               q_vector->eitr = adapter->rx_eitr_param;
                ixgbe_write_eitr(q_vector);
        }
 
index 45bf8b9716e39b0172fc2ac883967437b22ce8e4..c407bd9de0dd87644556efcb5b717a835c4657d6 100644 (file)
@@ -97,6 +97,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
         board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
         board_82599 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
+        board_82599 },
 
        /* required last entry */
        {0, }
@@ -924,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
                                              r_idx + 1);
                }
 
-               /* if this is a tx only vector halve the interrupt rate */
                if (q_vector->txr_count && !q_vector->rxr_count)
-                       q_vector->eitr = (adapter->eitr_param >> 1);
+                       /* tx only */
+                       q_vector->eitr = adapter->tx_eitr_param;
                else if (q_vector->rxr_count)
-                       /* rx only */
-                       q_vector->eitr = adapter->eitr_param;
+                       /* rx or mixed */
+                       q_vector->eitr = adapter->rx_eitr_param;
 
                ixgbe_write_eitr(q_vector);
        }
@@ -1357,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
        /* If all Rx work done, exit the polling mode */
        if (work_done < budget) {
                napi_complete(napi);
-               if (adapter->itr_setting & 1)
+               if (adapter->rx_itr_setting & 1)
                        ixgbe_set_itr_msix(q_vector);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        ixgbe_irq_enable_queues(adapter,
@@ -1418,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
        /* If all Rx work done, exit the polling mode */
        if (work_done < budget) {
                napi_complete(napi);
-               if (adapter->itr_setting & 1)
+               if (adapter->rx_itr_setting & 1)
                        ixgbe_set_itr_msix(q_vector);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        ixgbe_irq_enable_queues(adapter,
@@ -1456,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
        if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
                work_done = budget;
 
-       /* If all Rx work done, exit the polling mode */
+       /* If all Tx work done, exit the polling mode */
        if (work_done < budget) {
                napi_complete(napi);
-               if (adapter->itr_setting & 1)
+               if (adapter->tx_itr_setting & 1)
                        ixgbe_set_itr_msix(q_vector);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
@@ -1846,7 +1848,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
 
        IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
-                       EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
+                       EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
 
        ixgbe_set_ivar(adapter, 0, 0, 0);
        ixgbe_set_ivar(adapter, 1, 0, 0);
@@ -1967,6 +1969,50 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
        return mrqc;
 }
 
+/**
+ * ixgbe_configure_rscctl - enable RSC for the indicated ring
+ * @adapter:    address of board private structure
+ * @index:      index of ring to set
+ * @rx_buf_len: rx buffer length
+ **/
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index,
+                                   int rx_buf_len)
+{
+       struct ixgbe_ring *rx_ring;
+       struct ixgbe_hw *hw = &adapter->hw;
+       int j;
+       u32 rscctrl;
+
+       rx_ring = &adapter->rx_ring[index];
+       j = rx_ring->reg_idx;
+       rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
+       rscctrl |= IXGBE_RSCCTL_RSCEN;
+       /*
+        * we must limit the number of descriptors so that the
+        * total size of max desc * buf_len is not greater
+        * than 65535
+        */
+       if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+#if (MAX_SKB_FRAGS > 16)
+               rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+#elif (MAX_SKB_FRAGS > 8)
+               rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+#elif (MAX_SKB_FRAGS > 4)
+               rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+#else
+               rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
+#endif
+       } else {
+               if (rx_buf_len < IXGBE_RXBUFFER_4096)
+                       rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+               else if (rx_buf_len < IXGBE_RXBUFFER_8192)
+                       rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+               else
+                       rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+       }
+       IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
+}
+
 /**
  * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
  * @adapter: board private structure
@@ -1988,7 +2034,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
        u32 fctrl, hlreg0;
        u32 reta = 0, mrqc = 0;
        u32 rdrxctl;
-       u32 rscctrl;
        int rx_buf_len;
 
        /* Decide whether to use packet split mode or not */
@@ -2055,6 +2100,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 
                if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
                        rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED;
+               else
+                       rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
 
 #ifdef IXGBE_FCOE
                if (netdev->features & NETIF_F_FCOE_MTU) {
@@ -2144,36 +2191,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 
        if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                /* Enable 82599 HW-RSC */
-               for (i = 0; i < adapter->num_rx_queues; i++) {
-                       rx_ring = &adapter->rx_ring[i];
-                       j = rx_ring->reg_idx;
-                       rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
-                       rscctrl |= IXGBE_RSCCTL_RSCEN;
-                       /*
-                        * we must limit the number of descriptors so that the
-                        * total size of max desc * buf_len is not greater
-                        * than 65535
-                        */
-                       if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
-#if (MAX_SKB_FRAGS > 16)
-                               rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-#elif (MAX_SKB_FRAGS > 8)
-                               rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-#elif (MAX_SKB_FRAGS > 4)
-                               rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
-#else
-                               rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
-#endif
-                       } else {
-                               if (rx_buf_len < IXGBE_RXBUFFER_4096)
-                                       rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-                               else if (rx_buf_len < IXGBE_RXBUFFER_8192)
-                                       rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-                               else
-                                       rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
-                       }
-                       IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
-               }
+               for (i = 0; i < adapter->num_rx_queues; i++)
+                       ixgbe_configure_rscctl(adapter, i, rx_buf_len);
+
                /* Disable RSC for ACK packets */
                IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
                   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
@@ -2922,6 +2942,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 
        ixgbe_napi_disable_all(adapter);
 
+       clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+       del_timer_sync(&adapter->sfp_timer);
        del_timer_sync(&adapter->watchdog_timer);
        cancel_work_sync(&adapter->watchdog_task);
 
@@ -2985,7 +3007,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
        /* If budget not fully consumed, exit the polling mode */
        if (work_done < budget) {
                napi_complete(napi);
-               if (adapter->itr_setting & 1)
+               if (adapter->rx_itr_setting & 1)
                        ixgbe_set_itr(adapter);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
@@ -3595,7 +3617,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
                if (!q_vector)
                        goto err_out;
                q_vector->adapter = adapter;
-               q_vector->eitr = adapter->eitr_param;
+               if (q_vector->txr_count && !q_vector->rxr_count)
+                       q_vector->eitr = adapter->tx_eitr_param;
+               else
+                       q_vector->eitr = adapter->rx_eitr_param;
                q_vector->v_idx = q_idx;
                netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
                adapter->q_vector[q_idx] = q_vector;
@@ -3864,8 +3889,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
        hw->fc.disable_fc_autoneg = false;
 
        /* enable itr by default in dynamic mode */
-       adapter->itr_setting = 1;
-       adapter->eitr_param = 20000;
+       adapter->rx_itr_setting = 1;
+       adapter->rx_eitr_param = 20000;
+       adapter->tx_itr_setting = 1;
+       adapter->tx_eitr_param = 10000;
 
        /* set defaults for eitr in MegaBytes */
        adapter->eitr_low = 10;
index 8ba90eec1dc9fe1b7da78628106e1e4c2dd3d5dd..8761d7899f7d0704440d4bb3766bc671e4043750 100644 (file)
@@ -49,6 +49,7 @@
 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM      0x10E1
 #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
 #define IXGBE_DEV_ID_82599_KX4           0x10F7
+#define IXGBE_DEV_ID_82599_CX4           0x10F9
 #define IXGBE_DEV_ID_82599_SFP           0x10FB
 #define IXGBE_DEV_ID_82599_XAUI_LOM      0x10FC
 
@@ -2143,6 +2144,7 @@ enum ixgbe_media_type {
        ixgbe_media_type_fiber,
        ixgbe_media_type_copper,
        ixgbe_media_type_backplane,
+       ixgbe_media_type_cx4,
        ixgbe_media_type_virtual
 };
 
index aa9674b7f19ce5f8f980da832f7e9e49746c2733..f599294fa8abbe0f7195fb8a7e6b539a60faf618 100644 (file)
@@ -96,12 +96,17 @@ static void catas_reset(struct work_struct *work)
        spin_unlock_irq(&catas_lock);
 
        list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) {
+               struct pci_dev *pdev = priv->dev.pdev;
+
                ret = mlx4_restart_one(priv->dev.pdev);
-               dev = &priv->dev;
+               /* 'priv' now is not valid */
                if (ret)
-                       mlx4_err(dev, "Reset failed (%d)\n", ret);
-               else
+                       printk(KERN_ERR "mlx4 %s: Reset failed (%d)\n",
+                               pci_name(pdev), ret);
+               else {
+                       dev  = pci_get_drvdata(pdev);
                        mlx4_dbg(dev, "Reset succeeded\n");
+               }
        }
 }
 
index f7bdde111dfcba86f0bf821fd332c77580670738..b5aa974827e53bc5b69b209797b332028eec6a42 100644 (file)
@@ -1469,6 +1469,7 @@ netxen_nic_resume(struct pci_dev *pdev)
        }
 
        netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+       return 0;
 
 err_out_detach:
        netxen_nic_detach(adapter);
@@ -1903,12 +1904,13 @@ static void netxen_tx_timeout_task(struct work_struct *work)
 
                netif_wake_queue(adapter->netdev);
 
-               goto done;
+               clear_bit(__NX_RESETTING, &adapter->state);
 
        } else {
+               clear_bit(__NX_RESETTING, &adapter->state);
                if (!netxen_nic_reset_context(adapter)) {
                        adapter->netdev->trans_start = jiffies;
-                       goto done;
+                       return;
                }
 
                /* context reset failed, fall through for fw reset */
@@ -1916,8 +1918,6 @@ static void netxen_tx_timeout_task(struct work_struct *work)
 
 request_reset:
        adapter->need_fw_reset = 1;
-done:
-       clear_bit(__NX_RESETTING, &adapter->state);
 }
 
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
index 90a94d2158314341da9e915239d52452018cccfd..474876c879cba3579f8745e5927c1a1042af8334 100644 (file)
@@ -340,12 +340,11 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
        base = &virt[hw_info[i].offset & (req.Size-1)];
        if ((readb(base+0) == hw_info[i].a0) &&
            (readb(base+2) == hw_info[i].a1) &&
-           (readb(base+4) == hw_info[i].a2))
-           break;
-    }
-    if (i < NR_INFO) {
-       for (j = 0; j < 6; j++)
-           dev->dev_addr[j] = readb(base + (j<<1));
+           (readb(base+4) == hw_info[i].a2)) {
+               for (j = 0; j < 6; j++)
+                   dev->dev_addr[j] = readb(base + (j<<1));
+               break;
+       }
     }
 
     iounmap(virt);
@@ -1750,11 +1749,11 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
        /* too generic! */
        /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"),
index e0f9219a0aea8b60927d3ec0ef6861d8b1880261..cc394d073755413c1bae92367c727f172b6d11e3 100644 (file)
@@ -229,7 +229,7 @@ static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel);
 static atomic_t pppol2tp_tunnel_count;
 static atomic_t pppol2tp_session_count;
 static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
-static struct proto_ops pppol2tp_ops;
+static const struct proto_ops pppol2tp_ops;
 
 /* per-net private data for this module */
 static int pppol2tp_net_id;
@@ -2574,7 +2574,7 @@ static const struct file_operations pppol2tp_proc_fops = {
  * Init and cleanup
  *****************************************************************************/
 
-static struct proto_ops pppol2tp_ops = {
+static const struct proto_ops pppol2tp_ops = {
        .family         = AF_PPPOX,
        .owner          = THIS_MODULE,
        .release        = pppol2tp_release,
index 00bc65a0aac9e609156cfde1cdd719acb6ca2916..68d256b9638cc455e4ea1f5159ac5c0e711f80a0 100644 (file)
@@ -65,8 +65,8 @@
 #define RX_DEF_PENDING         RX_MAX_PENDING
 
 /* This is the worst case number of transmit list elements for a single skb:
-   VLAN + TSO + CKSUM + Data + skb_frags * DMA */
-#define MAX_SKB_TX_LE  (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS)
+   VLAN:GSO + CKSUM + Data + skb_frags * DMA */
+#define MAX_SKB_TX_LE  (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1))
 #define TX_MIN_PENDING         (MAX_SKB_TX_LE+1)
 #define TX_MAX_PENDING         4096
 #define TX_DEF_PENDING         127
@@ -1497,7 +1497,6 @@ static int sky2_up(struct net_device *dev)
        if (ramsize > 0) {
                u32 rxspace;
 
-               hw->flags |= SKY2_HW_RAM_BUFFER;
                pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
                if (ramsize < 16)
                        rxspace = ramsize / 2;
@@ -1567,11 +1566,13 @@ static unsigned tx_le_req(const struct sk_buff *skb)
 {
        unsigned count;
 
-       count = sizeof(dma_addr_t) / sizeof(u32);
-       count += skb_shinfo(skb)->nr_frags * count;
+       count = (skb_shinfo(skb)->nr_frags + 1)
+               * (sizeof(dma_addr_t) / sizeof(u32));
 
        if (skb_is_gso(skb))
                ++count;
+       else if (sizeof(dma_addr_t) == sizeof(u32))
+               ++count;        /* possible vlan */
 
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                ++count;
@@ -2924,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
                        ++hw->ports;
        }
 
+       if (sky2_read8(hw, B2_E_0))
+               hw->flags |= SKY2_HW_RAM_BUFFER;
+
        return 0;
 }
 
@@ -4548,16 +4552,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        if (hw->ports > 1) {
                struct net_device *dev1;
 
+               err = -ENOMEM;
                dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default);
-               if (!dev1)
-                       dev_warn(&pdev->dev, "allocation for second device failed\n");
-               else if ((err = register_netdev(dev1))) {
+               if (dev1 && (err = register_netdev(dev1)) == 0)
+                       sky2_show_addr(dev1);
+               else {
                        dev_warn(&pdev->dev,
                                 "register of second port failed (%d)\n", err);
                        hw->dev[1] = NULL;
-                       free_netdev(dev1);
-               } else
-                       sky2_show_addr(dev1);
+                       hw->ports = 1;
+                       if (dev1)
+                               free_netdev(dev1);
+               }
        }
 
        setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw);
index 57a159fac99fcc1308ae106e06aadb7602bfe496..9c8c6ed4a3cd7ac8b822d814d056eaee19f4579e 100644 (file)
@@ -83,34 +83,6 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
        }
 }
 
-#elif defined(CONFIG_BLACKFIN)
-
-#define SMC_IRQ_FLAGS          IRQF_TRIGGER_HIGH
-#define RPC_LSA_DEFAULT                RPC_LED_100_10
-#define RPC_LSB_DEFAULT                RPC_LED_TX_RX
-
-#define SMC_CAN_USE_8BIT       0
-#define SMC_CAN_USE_16BIT      1
-# if defined(CONFIG_BF561)
-#define SMC_CAN_USE_32BIT      1
-# else
-#define SMC_CAN_USE_32BIT      0
-# endif
-#define SMC_IO_SHIFT           0
-#define SMC_NOWAIT             1
-#define SMC_USE_BFIN_DMA       0
-
-#define SMC_inw(a, r)          readw((a) + (r))
-#define SMC_outw(v, a, r)      writew(v, (a) + (r))
-#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
-# if SMC_CAN_USE_32BIT
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
-# endif
-
 #elif defined(CONFIG_REDWOOD_5) || defined(CONFIG_REDWOOD_6)
 
 /* We can only do 16-bit reads and writes in the static memory space. */
index f1e5e4542c2a04084b419c990e67760e05253f82..bc74db0d12f37e0b015f1d6b0d099b9ed77f6bc2 100644 (file)
@@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = {
        .ndo_open               = vnet_open,
        .ndo_stop               = vnet_close,
        .ndo_set_multicast_list = vnet_set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = vnet_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = vnet_tx_timeout,
index 3f5d28851aa20e4b175a05133faf27161f199f0c..e091756166a3ad9a069b57c9ca52c2a404c65dfb 100644 (file)
@@ -946,8 +946,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                char *name;
                unsigned long flags = 0;
 
-               err = -EINVAL;
-
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                err = security_tun_dev_create();
@@ -964,7 +962,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                        flags |= TUN_TAP_DEV;
                        name = "tap%d";
                } else
-                       goto failed;
+                       return -EINVAL;
 
                if (*ifr->ifr_name)
                        name = ifr->ifr_name;
index 97e54d9d03ce760bea2b7178b646c82a41d87c5c..33d5c579c5add542772afb6bf4327bdbb0ebc90b 100644 (file)
@@ -264,7 +264,6 @@ static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        switch (cmd) {
        case SIOCPNGAUTOCONF:
                req->ifr_phonet_autoconf.device = PN_DEV_PC;
-               printk(KERN_CRIT"device is PN_DEV_PC\n");
                return 0;
        }
        return -ENOIOCTLCMD;
index e2a39b9be96e25fcea7faefca6328e1d3b2d3e2b..e391ef969c288c9ddec730895f8bd2cb96cbfab5 100644 (file)
@@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
                          int timeout)
 {
        struct usb_ctrlrequest *dr;
+       int retval;
 
        dbg("kaweth_control()");
 
@@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
                return -ENOMEM;
        }
 
-       dr->bRequestType= requesttype;
+       dr->bRequestType = requesttype;
        dr->bRequest = request;
        dr->wValue = cpu_to_le16(value);
        dr->wIndex = cpu_to_le16(index);
        dr->wLength = cpu_to_le16(size);
 
-       return kaweth_internal_control_msg(kaweth->dev,
-                                       pipe,
-                                       dr,
-                                       data,
-                                       size,
-                                       timeout);
+       retval = kaweth_internal_control_msg(kaweth->dev,
+                                            pipe,
+                                            dr,
+                                            data,
+                                            size,
+                                            timeout);
+
+       kfree(dr);
+       return retval;
 }
 
 /****************************************************************
index 938fb3530a7a779eee3344f2d4cd0dadfc07bdba..c6c922247d0558845bd18d2cf5c66cbf948dcaf7 100644 (file)
@@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = {
        .rx_fixup       = smsc95xx_rx_fixup,
        .tx_fixup       = smsc95xx_tx_fixup,
        .status         = smsc95xx_status,
-       .flags          = FLAG_ETHER,
+       .flags          = FLAG_ETHER | FLAG_SEND_ZLP,
 };
 
 static const struct usb_device_id products[] = {
@@ -1236,11 +1236,76 @@ static const struct usb_device_id products[] = {
                USB_DEVICE(0x0424, 0x9500),
                .driver_info = (unsigned long) &smsc95xx_info,
        },
+       {
+               /* SMSC9505 USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9505),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9500A USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9E00),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9505A USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9E01),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
        {
                /* SMSC9512/9514 USB Hub & Ethernet Device */
                USB_DEVICE(0x0424, 0xec00),
                .driver_info = (unsigned long) &smsc95xx_info,
        },
+       {
+               /* SMSC9500 USB Ethernet Device (SAL10) */
+               USB_DEVICE(0x0424, 0x9900),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9505 USB Ethernet Device (SAL10) */
+               USB_DEVICE(0x0424, 0x9901),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9500A USB Ethernet Device (SAL10) */
+               USB_DEVICE(0x0424, 0x9902),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9505A USB Ethernet Device (SAL10) */
+               USB_DEVICE(0x0424, 0x9903),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
+               USB_DEVICE(0x0424, 0x9904),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9500A USB Ethernet Device (HAL) */
+               USB_DEVICE(0x0424, 0x9905),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9505A USB Ethernet Device (HAL) */
+               USB_DEVICE(0x0424, 0x9906),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9500 USB Ethernet Device (Alternate ID) */
+               USB_DEVICE(0x0424, 0x9907),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9500A USB Ethernet Device (Alternate ID) */
+               USB_DEVICE(0x0424, 0x9908),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
+               USB_DEVICE(0x0424, 0x9909),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
        { },            /* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index 24b36f795151bd7a61c91260e95d56830fab29ed..ca5ca5ae061d755ba2ec97f4d8285d7c079680ee 100644 (file)
@@ -1049,7 +1049,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
         * NOTE:  strictly conforming cdc-ether devices should expect
         * the ZLP here, but ignore the one-byte packet.
         */
-       if ((length % dev->maxpacket) == 0) {
+       if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
                urb->transfer_buffer_length++;
                if (skb_tailroom(skb)) {
                        skb->data[skb->len] = 0;
index 6c0ea214a82e1e85c6f0d46b033b87ac9e99152d..9b907a36bb8c90608170d1505428c34f898e6164 100644 (file)
@@ -4367,6 +4367,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 
        ieee80211_wake_queues(dev->wl->hw);
 
+       ieee80211_wake_queues(dev->wl->hw);
+
        b43_set_status(dev, B43_STAT_INITIALIZED);
 
 out:
index d9169b47ac422fdfcd0eb6cc45088f97447fa56f..27298b19d5bd393592da7a165887ba21c0c97067 100644 (file)
@@ -644,11 +644,10 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 {
        struct wl1271 *wl = hw->priv;
        struct sk_buff *beacon;
-       DECLARE_MAC_BUF(mac);
        int ret;
 
-       wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
-                    print_mac(mac, conf->bssid));
+       wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM",
+                    conf->bssid);
        wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
                          conf->ssid_len);
 
index dc22782633a5b4ac58eb04c285055ccaa6f9c867..83a044dbd1d775dc9a3c88d39c2091c42b01ff36 100644 (file)
@@ -134,18 +134,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        }
 
        /* Enable the Rx interrupts for the first buffer */
-       reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
        out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
-                reg_data | XEL_RSR_RECV_IE_MASK);
+                XEL_RSR_RECV_IE_MASK);
 
        /* Enable the Rx interrupts for the second Buffer if
         * configured in HW */
        if (drvdata->rx_ping_pong != 0) {
-               reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_RSR_OFFSET);
                out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
                         XEL_RSR_OFFSET,
-                        reg_data | XEL_RSR_RECV_IE_MASK);
+                        XEL_RSR_RECV_IE_MASK);
        }
 
        /* Enable the Global Interrupt Enable */
index 79c9c5f5cdbae6995774d88b22fa61b370bc4eb3..ed4648b556c775a030f27a967fab4d543f26ea6a 100644 (file)
@@ -868,11 +868,11 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
        PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
        PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
@@ -883,10 +883,10 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
        PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
        PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
-       PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
        PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
        PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100  1.00.",0x19ca78af,0xf964f42b),
        PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
index 975ecddbce30b48a4b20ed5ac955a48d7f224405..5e4b8655b57cd5ce0491e3d34e860c96a63ff7fd 100644 (file)
@@ -121,8 +121,6 @@ source "drivers/staging/serqt_usb2/Kconfig"
 
 source "drivers/staging/vt6655/Kconfig"
 
-source "drivers/staging/cpc-usb/Kconfig"
-
 source "drivers/staging/pata_rdc/Kconfig"
 
 source "drivers/staging/udlfb/Kconfig"
index 2241ae1b21ee1ad47927386c6c5e4e2af4f83f4f..ede1599e7e663889b6a525fbd0132c0845958e3c 100644 (file)
@@ -42,6 +42,5 @@ obj-$(CONFIG_LINE6_USB)               += line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)      += serqt_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)  += octeon/
 obj-$(CONFIG_VT6655)           += vt6655/
-obj-$(CONFIG_USB_CPC)          += cpc-usb/
 obj-$(CONFIG_RDC_17F3101X)     += pata_rdc/
 obj-$(CONFIG_FB_UDL)           += udlfb/
diff --git a/drivers/staging/cpc-usb/Kconfig b/drivers/staging/cpc-usb/Kconfig
deleted file mode 100644 (file)
index 2be0bc9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-config USB_CPC
-       tristate "CPC CAN USB driver"
-       depends on USB && PROC_FS
-       default n
diff --git a/drivers/staging/cpc-usb/Makefile b/drivers/staging/cpc-usb/Makefile
deleted file mode 100644 (file)
index 3f83170..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_USB_CPC)  += cpc-usb.o
-
-cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o
diff --git a/drivers/staging/cpc-usb/TODO b/drivers/staging/cpc-usb/TODO
deleted file mode 100644 (file)
index 000e8bb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Things to do for this driver to get merged into the main portion of the
-kernel:
-       - checkpatch cleanups
-       - sparse clean
-       - remove proc code
-       - tie into CAN socket interfaces if possible
-       - figure out sane userspace api
-
-Send patches to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/cpc-usb/cpc-usb_drv.c b/drivers/staging/cpc-usb/cpc-usb_drv.c
deleted file mode 100644 (file)
index 9bf3f98..0000000
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * CPC-USB CAN Interface Kernel Driver
- *
- * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include <linux/version.h>
-
-#include <linux/proc_fs.h>
-
-#include "cpc.h"
-
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/* Version Information */
-#define DRIVER_AUTHOR  "Sebastian Haas <haas@ems-wuensche.com>"
-#define DRIVER_DESC    "CPC-USB Driver for Linux Kernel 2.6"
-#define DRIVER_VERSION CPC_DRIVER_VERSION
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-
-/* Define these values to match your devices */
-#define USB_CPCUSB_VENDOR_ID   0x12D6
-
-#define USB_CPCUSB_M16C_PRODUCT_ID    0x0888
-#define USB_CPCUSB_LPC2119_PRODUCT_ID 0x0444
-
-#define CPC_USB_PROC_DIR     CPC_PROC_DIR "cpc-usb"
-
-static struct proc_dir_entry *procDir;
-static struct proc_dir_entry *procEntry;
-
-/* Module parameters */
-static int debug;
-module_param(debug, int, S_IRUGO);
-
-/* table of devices that work with this driver */
-static struct usb_device_id cpcusb_table[] = {
-       {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_M16C_PRODUCT_ID)},
-       {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_LPC2119_PRODUCT_ID)},
-       {}                      /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, cpcusb_table);
-
-/* use to prevent kernel panic if driver is unloaded
- * while a programm has still open the device
- */
-DECLARE_WAIT_QUEUE_HEAD(rmmodWq);
-atomic_t useCount;
-
-static CPC_USB_T *CPCUSB_Table[CPC_USB_CARD_CNT] = { 0 };
-static unsigned int CPCUsbCnt;
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
-
-/* local function prototypes */
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-                          loff_t *ppos);
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-                           size_t count, loff_t *ppos);
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait);
-static int cpcusb_open(struct inode *inode, struct file *file);
-static int cpcusb_release(struct inode *inode, struct file *file);
-
-static int cpcusb_probe(struct usb_interface *interface,
-                       const struct usb_device_id *id);
-static void cpcusb_disconnect(struct usb_interface *interface);
-
-static void cpcusb_read_bulk_callback(struct urb *urb);
-static void cpcusb_write_bulk_callback(struct urb *urb);
-static void cpcusb_read_interrupt_callback(struct urb *urb);
-
-static int cpcusb_setup_intrep(CPC_USB_T *card);
-
-static struct file_operations cpcusb_fops = {
-       /*
-        * The owner field is part of the module-locking
-        * mechanism. The idea is that the kernel knows
-        * which module to increment the use-counter of
-        * BEFORE it calls the device's open() function.
-        * This also means that the kernel can decrement
-        * the use-counter again before calling release()
-        * or should the open() function fail.
-        */
-       .owner = THIS_MODULE,
-
-       .read = cpcusb_read,
-       .write = cpcusb_write,
-       .poll = cpcusb_poll,
-       .open = cpcusb_open,
-       .release = cpcusb_release,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver cpcusb_class = {
-       .name = "usb/cpc_usb%d",
-       .fops = &cpcusb_fops,
-       .minor_base = CPC_USB_BASE_MNR,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver cpcusb_driver = {
-       .name = "cpc-usb",
-       .probe = cpcusb_probe,
-       .disconnect = cpcusb_disconnect,
-       .id_table = cpcusb_table,
-};
-
-static int cpcusb_create_info_output(char *buf)
-{
-       int i = 0, j;
-
-       for (j = 0; j < CPC_USB_CARD_CNT; j++) {
-               if (CPCUSB_Table[j]) {
-                       CPC_USB_T *card = CPCUSB_Table[j];
-                       CPC_CHAN_T *chan = card->chan;
-
-                       /* MINOR CHANNELNO BUSNO SLOTNO */
-                       i += sprintf(&buf[i], "%d %s\n", chan->minor,
-                                    card->serialNumber);
-               }
-       }
-
-       return i;
-}
-
-static int cpcusb_proc_read_info(char *page, char **start, off_t off,
-                                int count, int *eof, void *data)
-{
-       int len = cpcusb_create_info_output(page);
-
-       if (len <= off + count)
-               *eof = 1;
-       *start = page + off;
-       len -= off;
-       if (len > count)
-               len = count;
-       if (len < 0)
-               len = 0;
-
-       return len;
-}
-
-/*
- * Remove CPC-USB and cleanup
- */
-static inline void cpcusb_delete(CPC_USB_T *card)
-{
-       if (card) {
-               if (card->chan) {
-                       if (card->chan->buf)
-                               vfree(card->chan->buf);
-
-                       if (card->chan->CPCWait_q)
-                               kfree(card->chan->CPCWait_q);
-
-                       kfree(card->chan);
-               }
-
-               CPCUSB_Table[card->idx] = NULL;
-               kfree(card);
-       }
-}
-
-/*
- * setup the interrupt IN endpoint of a specific CPC-USB device
- */
-static int cpcusb_setup_intrep(CPC_USB_T *card)
-{
-       int retval = 0;
-       struct usb_endpoint_descriptor *ep;
-
-       ep = &card->interface->altsetting[0].endpoint[card->num_intr_in].desc;
-
-       card->intr_in_buffer[0] = 0;
-       card->free_slots = 15;  /* initial size */
-
-       /* setup the urb */
-       usb_fill_int_urb(card->intr_in_urb, card->udev,
-                        usb_rcvintpipe(card->udev, card->num_intr_in),
-                        card->intr_in_buffer,
-                        sizeof(card->intr_in_buffer),
-                        cpcusb_read_interrupt_callback,
-                        card,
-                        ep->bInterval);
-
-       card->intr_in_urb->status = 0;  /* needed! */
-
-       /* submit the urb */
-       retval = usb_submit_urb(card->intr_in_urb, GFP_KERNEL);
-
-       if (retval)
-               err("%s - failed submitting intr urb, error %d", __func__,
-                   retval);
-
-       return retval;
-}
-
-static int cpcusb_open(struct inode *inode, struct file *file)
-{
-       CPC_USB_T *card = NULL;
-       struct usb_interface *interface;
-       int subminor;
-       int j, retval = 0;
-
-       subminor = iminor(inode);
-
-       /* prevent disconnects */
-       down(&disconnect_sem);
-
-       interface = usb_find_interface(&cpcusb_driver, subminor);
-       if (!interface) {
-               err("%s - error, can't find device for minor %d",
-                               __func__, subminor);
-               retval = CPC_ERR_NO_INTERFACE_PRESENT;
-               goto exit_no_device;
-       }
-
-       card = usb_get_intfdata(interface);
-       if (!card) {
-               retval = CPC_ERR_NO_INTERFACE_PRESENT;
-               goto exit_no_device;
-       }
-
-       /* lock this device */
-       down(&card->sem);
-
-       /* increment our usage count for the driver */
-       if (card->open) {
-               dbg("device already opened");
-               retval = CPC_ERR_CHANNEL_ALREADY_OPEN;
-               goto exit_on_error;
-       }
-
-       /* save our object in the file's private structure */
-       file->private_data = card;
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               usb_fill_bulk_urb(card->urbs[j].urb, card->udev,
-                                 usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-                                 card->urbs[j].buffer, card->urbs[j].size,
-                                 cpcusb_read_bulk_callback, card);
-
-               retval = usb_submit_urb(card->urbs[j].urb, GFP_KERNEL);
-
-               if (retval) {
-                       err("%s - failed submitting read urb, error %d",
-                           __func__, retval);
-                       retval = CPC_ERR_TRANSMISSION_FAILED;
-                       goto exit_on_error;
-               }
-       }
-
-       info("%s - %d URB's submitted", __func__, j);
-
-       ResetBuffer(card->chan);
-
-       cpcusb_setup_intrep(card);
-       card->open = 1;
-
-       atomic_inc(&useCount);
-
-exit_on_error:
-       /* unlock this device */
-       up(&card->sem);
-
-exit_no_device:
-       up(&disconnect_sem);
-
-       return retval;
-}
-
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait)
-{
-       CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-       unsigned int retval = 0;
-
-       if (!card) {
-               err("%s - device object lost", __func__);
-               return -EIO;
-       }
-
-       poll_wait(file, card->chan->CPCWait_q, wait);
-
-       if (IsBufferNotEmpty(card->chan) || !(card->present))
-               retval |= (POLLIN | POLLRDNORM);
-
-       if (card->free_slots)
-               retval |= (POLLOUT | POLLWRNORM);
-
-       return retval;
-}
-
-static int cpcusb_release(struct inode *inode, struct file *file)
-{
-       CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-       int j, retval = 0;
-
-       if (card == NULL) {
-               dbg("%s - object is NULL", __func__);
-               return CPC_ERR_NO_INTERFACE_PRESENT;
-       }
-
-       /* lock our device */
-       down(&card->sem);
-
-       if (!card->open) {
-               dbg("%s - device not opened", __func__);
-               retval = CPC_ERR_NO_INTERFACE_PRESENT;
-               goto exit_not_opened;
-       }
-
-       /* if device wasn't unplugged kill all urbs */
-       if (card->present) {
-               /* kill read urbs */
-               for (j = 0; j < CPC_USB_URB_CNT; j++) {
-                       usb_kill_urb(card->urbs[j].urb);
-               }
-
-               /* kill irq urb */
-               usb_kill_urb(card->intr_in_urb);
-
-               /* kill write urbs */
-               for (j = 0; j < CPC_USB_URB_CNT; j++) {
-                       if (atomic_read(&card->wrUrbs[j].busy)) {
-                               usb_kill_urb(card->wrUrbs[j].urb);
-                               wait_for_completion(&card->wrUrbs[j].finished);
-                       }
-               }
-       }
-
-       atomic_dec(&useCount);
-
-       /* last process detached */
-       if (atomic_read(&useCount) == 0) {
-               wake_up(&rmmodWq);
-       }
-
-       if (!card->present && card->open) {
-               /* the device was unplugged before the file was released */
-               up(&card->sem);
-               cpcusb_delete(card);
-               return 0;
-       }
-
-       card->open = 0;
-
-exit_not_opened:
-       up(&card->sem);
-
-       return 0;
-}
-
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-                          loff_t *ppos)
-{
-       CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-       CPC_CHAN_T *chan;
-       int retval = 0;
-
-       if (count < sizeof(CPC_MSG_T))
-               return CPC_ERR_UNKNOWN;
-
-       /* check if can read from the given address */
-       if (!access_ok(VERIFY_WRITE, buffer, count))
-               return CPC_ERR_UNKNOWN;
-
-       /* lock this object */
-       down(&card->sem);
-
-       /* verify that the device wasn't unplugged */
-       if (!card->present) {
-               up(&card->sem);
-               return CPC_ERR_NO_INTERFACE_PRESENT;
-       }
-
-       if (IsBufferEmpty(card->chan)) {
-               retval = 0;
-       } else {
-               chan = card->chan;
-
-#if 0
-               /* convert LPC2119 params back to SJA1000 params */
-               if (card->deviceRevision >= 0x0200
-                   && chan->buf[chan->oidx].type == CPC_MSG_T_CAN_PRMS) {
-                       LPC2119_TO_SJA1000_Params(&chan->buf[chan->oidx]);
-               }
-#endif
-
-               if (copy_to_user(buffer, &chan->buf[chan->oidx], count) != 0) {
-                       retval = CPC_ERR_IO_TRANSFER;
-               } else {
-                       chan->oidx = (chan->oidx + 1) % CPC_MSG_BUF_CNT;
-                       chan->WnR = 1;
-                       retval = sizeof(CPC_MSG_T);
-               }
-       }
-/*     spin_unlock_irqrestore(&card->slock, flags); */
-
-       /* unlock the device */
-       up(&card->sem);
-
-       return retval;
-}
-
-#define SHIFT  1
-static inline void cpcusb_align_buffer_alignment(unsigned char *buf)
-{
-       /* CPC-USB uploads packed bytes. */
-       CPC_MSG_T *cpc = (CPC_MSG_T *) buf;
-       unsigned int i;
-
-       for (i = 0; i < cpc->length + (2 * sizeof(unsigned long)); i++) {
-               ((unsigned char *) &cpc->msgid)[1 + i] =
-                   ((unsigned char *) &cpc->msgid)[1 + SHIFT + i];
-       }
-}
-
-static int cpc_get_buffer_count(CPC_CHAN_T *chan)
-{
-       /* check the buffer parameters */
-       if (chan->iidx == chan->oidx)
-               return !chan->WnR ? CPC_MSG_BUF_CNT : 0;
-       else if (chan->iidx >= chan->oidx)
-               return (chan->iidx - chan->oidx) % CPC_MSG_BUF_CNT;
-
-       return (chan->iidx + CPC_MSG_BUF_CNT - chan->oidx) % CPC_MSG_BUF_CNT;
-}
-
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-                           size_t count, loff_t *ppos)
-{
-       CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-       CPC_USB_WRITE_URB_T *wrUrb = NULL;
-
-       ssize_t bytes_written = 0;
-       int retval = 0;
-       int j;
-
-       unsigned char *obuf = NULL;
-       unsigned char type = 0;
-       CPC_MSG_T *info = NULL;
-
-       dbg("%s - entered minor %d, count = %zu, present = %d",
-           __func__, card->minor, count, card->present);
-
-       if (count > sizeof(CPC_MSG_T))
-               return CPC_ERR_UNKNOWN;
-
-       /* check if can read from the given address */
-       if (!access_ok(VERIFY_READ, buffer, count))
-               return CPC_ERR_UNKNOWN;
-
-       /* lock this object */
-       down(&card->sem);
-
-       /* verify that the device wasn't unplugged */
-       if (!card->present) {
-               retval = CPC_ERR_NO_INTERFACE_PRESENT;
-               goto exit;
-       }
-
-       /* verify that we actually have some data to write */
-       if (count == 0) {
-               dbg("%s - write request of 0 bytes", __func__);
-               goto exit;
-       }
-
-       if (card->free_slots <= 5) {
-               info = (CPC_MSG_T *) buffer;
-
-               if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE
-                   || card->free_slots <= 0) {
-                       dbg("%s - send buffer full please try again %d",
-                           __func__, card->free_slots);
-                       retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-                       goto exit;
-               }
-       }
-
-       /* Find a free write urb */
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               if (!atomic_read(&card->wrUrbs[j].busy)) {
-                       wrUrb = &card->wrUrbs[j];       /* remember found URB */
-                       atomic_set(&wrUrb->busy, 1);    /* lock this URB      */
-                       init_completion(&wrUrb->finished);      /* init completion    */
-                       dbg("WR URB no. %d started", j);
-                       break;
-               }
-       }
-
-       /* don't found write urb say error */
-       if (!wrUrb) {
-               dbg("%s - no free send urb available", __func__);
-               retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-               goto exit;
-       }
-       dbg("URB write req");
-
-       obuf = (unsigned char *) wrUrb->urb->transfer_buffer;
-
-       /* copy the data from userspace into our transfer buffer;
-        * this is the only copy required.
-        */
-       if (copy_from_user(&obuf[4], buffer, count) != 0) {
-               atomic_set(&wrUrb->busy, 0);    /* release urb */
-               retval = CPC_ERR_IO_TRANSFER;
-               goto exit;
-       }
-
-       /* check if it is a DRIVER information message, so we can
-        * response to that message and not the USB
-        */
-       info = (CPC_MSG_T *) &obuf[4];
-
-       bytes_written = 11 + info->length;
-       if (bytes_written >= wrUrb->size) {
-               retval = CPC_ERR_IO_TRANSFER;
-               goto exit;
-       }
-
-       switch (info->type) {
-       case CPC_CMD_T_CLEAR_MSG_QUEUE:
-               ResetBuffer(card->chan);
-               break;
-
-       case CPC_CMD_T_INQ_MSG_QUEUE_CNT:
-               retval = cpc_get_buffer_count(card->chan);
-               atomic_set(&wrUrb->busy, 0);
-
-               goto exit;
-
-       case CPC_CMD_T_INQ_INFO:
-               if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) {
-                       /* release urb cause we'll use it for driver
-                        * information
-                        */
-                       atomic_set(&wrUrb->busy, 0);
-                       if (IsBufferFull(card->chan)) {
-                               retval = CPC_ERR_IO_TRANSFER;
-                               goto exit;
-                       }
-
-                       /* it is a driver information request message and we have
-                        * free rx slots to store the response
-                        */
-                       type = info->msg.info.type;
-                       info = &card->chan->buf[card->chan->iidx];
-
-                       info->type = CPC_MSG_T_INFO;
-                       info->msg.info.source = CPC_INFOMSG_T_DRIVER;
-                       info->msg.info.type = type;
-
-                       switch (type) {
-                       case CPC_INFOMSG_T_VERSION:
-                               info->length = strlen(CPC_DRIVER_VERSION) + 2;
-                               sprintf(info->msg.info.msg, "%s\n",
-                                       CPC_DRIVER_VERSION);
-                               break;
-
-                       case CPC_INFOMSG_T_SERIAL:
-                               info->length = strlen(CPC_DRIVER_SERIAL) + 2;
-                               sprintf(info->msg.info.msg, "%s\n",
-                                       CPC_DRIVER_SERIAL);
-                               break;
-
-                       default:
-                               info->length = 2;
-                               info->msg.info.type =
-                                   CPC_INFOMSG_T_UNKNOWN_TYPE;
-                       }
-
-                       card->chan->WnR = 0;
-                       card->chan->iidx =
-                           (card->chan->iidx + 1) % CPC_MSG_BUF_CNT;
-
-                       retval = info->length;
-                       goto exit;
-               }
-               break;
-       case CPC_CMD_T_CAN_PRMS:
-               /* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */
-               if (info->msg.canparams.cc_type != SJA1000
-                   && info->msg.canparams.cc_type != M16C_BASIC
-                   && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID
-                       && info->msg.canparams.cc_type != SJA1000)) {
-                       /* don't forget to release the urb */
-                       atomic_set(&wrUrb->busy, 0);
-                       retval = CPC_ERR_WRONG_CONTROLLER_TYPE;
-                       goto exit;
-               }
-               break;
-       }
-
-       /* just convert the params if it is an old CPC-USB with M16C controller */
-       if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) {
-               /* if it is a parameter message convert it from SJA1000 controller
-                * settings to M16C Basic controller settings
-                */
-               SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]);
-       }
-
-       /* don't forget the byte alignment */
-       cpcusb_align_buffer_alignment(&obuf[4]);
-
-       /* setup a the 4 byte header */
-       obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0;
-
-       /* this urb was already set up, except for this write size */
-       wrUrb->urb->transfer_buffer_length = bytes_written + 4;
-
-       /* send the data out the bulk port */
-       /* a character device write uses GFP_KERNEL,
-          unless a spinlock is held */
-       retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL);
-       if (retval) {
-               atomic_set(&wrUrb->busy, 0);    /* release urb */
-               err("%s - failed submitting write urb, error %d",
-                   __func__, retval);
-       } else {
-               retval = bytes_written;
-       }
-
-exit:
-       /* unlock the device */
-       up(&card->sem);
-
-       dbg("%s - leaved", __func__);
-
-       return retval;
-}
-
-/*
- * callback for interrupt IN urb
- */
-static void cpcusb_read_interrupt_callback(struct urb *urb)
-{
-       CPC_USB_T *card = (CPC_USB_T *) urb->context;
-       int retval;
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->slock, flags);
-
-       if (!card->present) {
-               spin_unlock_irqrestore(&card->slock, flags);
-               info("%s - no such device", __func__);
-               return;
-       }
-
-       switch (urb->status) {
-       case 0: /* success */
-               card->free_slots = card->intr_in_buffer[1];
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* urb was killed */
-               spin_unlock_irqrestore(&card->slock, flags);
-               dbg("%s - intr urb killed", __func__);
-               return;
-       default:
-               info("%s - nonzero urb status %d", __func__, urb->status);
-               break;
-       }
-
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval) {
-               err("%s - failed resubmitting intr urb, error %d",
-                   __func__, retval);
-       }
-
-       spin_unlock_irqrestore(&card->slock, flags);
-       wake_up_interruptible(card->chan->CPCWait_q);
-
-       return;
-}
-
-#define UN_SHIFT  1
-#define CPCMSG_HEADER_LEN_FIRMWARE   11
-static inline int cpcusb_unalign_and_copy_buffy(unsigned char *out,
-                                               unsigned char *in)
-{
-       unsigned int i, j;
-
-       for (i = 0; i < 3; i++)
-               out[i] = in[i];
-
-       for (j = 0; j < (in[1] + (CPCMSG_HEADER_LEN_FIRMWARE - 3)); j++)
-               out[j + i + UN_SHIFT] = in[j + i];
-
-       return i + j;
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_read_bulk_callback(struct urb *urb)
-{
-       CPC_USB_T *card = (CPC_USB_T *) urb->context;
-       CPC_CHAN_T *chan;
-       unsigned char *ibuf = urb->transfer_buffer;
-       int retval, msgCnt, start, again = 0;
-       unsigned long flags;
-
-       if (!card) {
-               err("%s - device object lost", __func__);
-               return;
-       }
-
-       spin_lock_irqsave(&card->slock, flags);
-
-       if (!card->present) {
-               spin_unlock_irqrestore(&card->slock, flags);
-               info("%s - no such device", __func__);
-               return;
-       }
-
-       switch (urb->status) {
-       case 0:         /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* urb was killed */
-               spin_unlock_irqrestore(&card->slock, flags);
-               dbg("%s - read urb killed", __func__);
-               return;
-       default:
-               info("%s - nonzero urb status %d", __func__, urb->status);
-               break;
-       }
-
-       if (urb->actual_length) {
-               msgCnt = ibuf[0] & ~0x80;
-               again = ibuf[0] & 0x80;
-
-               /* we have a 4 byte header */
-               start = 4;
-               chan = card->chan;
-               while (msgCnt) {
-                       if (!(IsBufferFull(card->chan))) {
-                               start +=
-                                   cpcusb_unalign_and_copy_buffy((unsigned char *)
-                                                         &chan->buf[chan->iidx], &ibuf[start]);
-
-                               if (start > urb->transfer_buffer_length) {
-                                       err("%d > %d", start, urb->transfer_buffer_length);
-                                       break;
-                               }
-
-                               chan->WnR = 0;
-                               chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT;
-                               msgCnt--;
-                       } else {
-                               break;
-                       }
-               }
-       }
-
-       usb_fill_bulk_urb(urb, card->udev,
-                         usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-                         urb->transfer_buffer,
-                         urb->transfer_buffer_length,
-                         cpcusb_read_bulk_callback, card);
-
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-
-       if (retval) {
-               err("%s - failed resubmitting read urb, error %d", __func__, retval);
-       }
-
-       spin_unlock_irqrestore(&card->slock, flags);
-
-       wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_write_bulk_callback(struct urb *urb)
-{
-       CPC_USB_T *card = (CPC_USB_T *) urb->context;
-       unsigned long flags;
-       int j;
-
-       spin_lock_irqsave(&card->slock, flags);
-
-       /* find this urb */
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               if (card->wrUrbs[j].urb == urb) {
-                       dbg("URB found no. %d", j);
-                       /* notify anyone waiting that the write has finished */
-                       complete(&card->wrUrbs[j].finished);
-                       atomic_set(&card->wrUrbs[j].busy, 0);
-                       break;
-               }
-       }
-
-       switch (urb->status) {
-       case 0:         /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* urb was killed */
-               spin_unlock_irqrestore(&card->slock, flags);
-               dbg("%s - write urb no. %d killed", __func__, j);
-               return;
-       default:
-               info("%s - nonzero urb status %d", __func__, urb->status);
-               break;
-       }
-
-       spin_unlock_irqrestore(&card->slock, flags);
-
-       wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-static inline int cpcusb_get_free_slot(void)
-{
-       int i;
-
-       for (i = 0; i < CPC_USB_CARD_CNT; i++) {
-               if (!CPCUSB_Table[i])
-                       return i;
-       }
-
-       return -1;
-}
-
-/*
- * probe function for new CPC-USB devices
- */
-static int cpcusb_probe(struct usb_interface *interface,
-                       const struct usb_device_id *id)
-{
-       CPC_USB_T *card = NULL;
-       CPC_CHAN_T *chan = NULL;
-
-       struct usb_device *udev = interface_to_usbdev(interface);
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-
-       int i, j, retval = -ENOMEM, slot;
-
-       slot = cpcusb_get_free_slot();
-       if (slot < 0) {
-               info("No more devices supported");
-               return -ENOMEM;
-       }
-
-       /* allocate memory for our device state and initialize it */
-       card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL);
-       if (!card) {
-               err("Out of memory");
-               return -ENOMEM;
-       }
-       CPCUSB_Table[slot] = card;
-
-       /* allocate and initialize the channel struct */
-       card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL);
-       if (!card->chan) {
-               kfree(card);
-               err("Out of memory");
-               return -ENOMEM;
-       }
-
-       chan = card->chan;
-       memset(chan, 0, sizeof(CPC_CHAN_T));
-       ResetBuffer(chan);
-
-       init_MUTEX(&card->sem);
-       spin_lock_init(&card->slock);
-
-       card->udev = udev;
-       card->interface = interface;
-       if (udev->descriptor.iSerialNumber) {
-               usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber,
-                                  128);
-               info("Serial %s", card->serialNumber);
-       }
-
-       card->productId = udev->descriptor.idProduct;
-       info("Product %s",
-            card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ?
-                        "CPC-USB/ARM7" : "CPC-USB/M16C");
-
-       /* set up the endpoint information */
-       /* check out the endpoints */
-       /* use only the first bulk-in and bulk-out endpoints */
-       iface_desc = &interface->altsetting[0];
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-
-               if (!card->num_intr_in &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                    == USB_ENDPOINT_XFER_INT)) {
-                       card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       card->num_intr_in = 1;
-
-                       if (!card->intr_in_urb) {
-                               err("No free urbs available");
-                               goto error;
-                       }
-
-                       dbg("intr_in urb %d", card->num_intr_in);
-               }
-
-               if (!card->num_bulk_in &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                    == USB_ENDPOINT_XFER_BULK)) {
-                       card->num_bulk_in = 2;
-                       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-                               card->urbs[j].size = endpoint->wMaxPacketSize;
-                               card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL);
-                               if (!card->urbs[j].urb) {
-                                       err("No free urbs available");
-                                       goto error;
-                               }
-                               card->urbs[j].buffer =
-                                   usb_buffer_alloc(udev,
-                                                    card->urbs[j].size,
-                                                    GFP_KERNEL,
-                                                    &card->urbs[j].urb->transfer_dma);
-                               if (!card->urbs[j].buffer) {
-                                       err("Couldn't allocate bulk_in_buffer");
-                                       goto error;
-                               }
-                       }
-                       info("%s - %d reading URB's allocated",
-                            __func__, CPC_USB_URB_CNT);
-               }
-
-               if (!card->num_bulk_out &&
-                   !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                    == USB_ENDPOINT_XFER_BULK)) {
-
-                       card->num_bulk_out = 2;
-
-                       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-                               card->wrUrbs[j].size =
-                                   endpoint->wMaxPacketSize;
-                               card->wrUrbs[j].urb =
-                                   usb_alloc_urb(0, GFP_KERNEL);
-                               if (!card->wrUrbs[j].urb) {
-                                       err("No free urbs available");
-                                       goto error;
-                               }
-                               card->wrUrbs[j].buffer = usb_buffer_alloc(udev,
-                                                              card->wrUrbs[j].size, GFP_KERNEL,
-                                                              &card->wrUrbs[j].urb->transfer_dma);
-
-                               if (!card->wrUrbs[j].buffer) {
-                                       err("Couldn't allocate bulk_out_buffer");
-                                       goto error;
-                               }
-
-                               usb_fill_bulk_urb(card->wrUrbs[j].urb, udev,
-                                               usb_sndbulkpipe(udev, endpoint->bEndpointAddress),
-                                               card->wrUrbs[j].buffer,
-                                               card->wrUrbs[j].size,
-                                               cpcusb_write_bulk_callback,
-                                               card);
-                       }
-
-                       info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT);
-               }
-       }
-
-       if (!(card->num_bulk_in && card->num_bulk_out)) {
-               err("Couldn't find both bulk-in and bulk-out endpoints");
-               goto error;
-       }
-
-       /* allow device read, write and ioctl */
-       card->present = 1;
-
-       /* we can register the device now, as it is ready */
-       usb_set_intfdata(interface, card);
-       retval = usb_register_dev(interface, &cpcusb_class);
-
-       if (retval) {
-               /* something prevented us from registering this driver */
-               err("Not able to get a minor for this device.");
-               usb_set_intfdata(interface, NULL);
-               goto error;
-       }
-
-       card->chan->minor = card->minor = interface->minor;
-
-       chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-       if (chan->buf == NULL) {
-               err("Out of memory");
-               retval = -ENOMEM;
-               goto error;
-       }
-       info("Allocated memory for %d messages (%lu kbytes)",
-            CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000);
-       memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-
-       ResetBuffer(chan);
-
-       card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
-       if (!card->chan->CPCWait_q) {
-               err("Out of memory");
-               retval = -ENOMEM;
-               goto error;
-       }
-       init_waitqueue_head(card->chan->CPCWait_q);
-
-       CPCUSB_Table[slot] = card;
-       card->idx = slot;
-       CPCUsbCnt++;
-
-       /* let the user know what node this device is now attached to */
-       info("Device now attached to USB-%d", card->minor);
-       return 0;
-
-error:
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               if (card->urbs[j].buffer) {
-                       usb_buffer_free(card->udev, card->urbs[j].size,
-                                       card->urbs[j].buffer,
-                                       card->urbs[j].urb->transfer_dma);
-                       card->urbs[j].buffer = NULL;
-               }
-               if (card->urbs[j].urb) {
-                       usb_free_urb(card->urbs[j].urb);
-                       card->urbs[j].urb = NULL;
-               }
-       }
-
-       cpcusb_delete(card);
-       return retval;
-}
-
-/*
- * called by the usb core when the device is removed from the system
- */
-static void cpcusb_disconnect(struct usb_interface *interface)
-{
-       CPC_USB_T *card = NULL;
-       int minor, j;
-
-       /* prevent races with open() */
-       down(&disconnect_sem);
-
-       card = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       down(&card->sem);
-
-       /* prevent device read, write and ioctl */
-       card->present = 0;
-
-       minor = card->minor;
-
-       /* free all urbs and their buffers */
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               /* terminate an ongoing write */
-               if (atomic_read(&card->wrUrbs[j].busy)) {
-                       usb_kill_urb(card->wrUrbs[j].urb);
-                       wait_for_completion(&card->wrUrbs[j].finished);
-               }
-               usb_buffer_free(card->udev, card->wrUrbs[j].size,
-                               card->wrUrbs[j].buffer,
-                               card->wrUrbs[j].urb->transfer_dma);
-               usb_free_urb(card->wrUrbs[j].urb);
-       }
-       info("%d write URBs freed", CPC_USB_URB_CNT);
-
-       /* free all urbs and their buffers */
-       for (j = 0; j < CPC_USB_URB_CNT; j++) {
-               usb_buffer_free(card->udev, card->urbs[j].size,
-                               card->urbs[j].buffer,
-                               card->urbs[j].urb->transfer_dma);
-               usb_free_urb(card->urbs[j].urb);
-       }
-       info("%d read URBs freed", CPC_USB_URB_CNT);
-       usb_free_urb(card->intr_in_urb);
-
-       /* give back our minor */
-       usb_deregister_dev(interface, &cpcusb_class);
-
-       up(&card->sem);
-
-       /* if the device is opened, cpcusb_release will clean this up */
-       if (!card->open)
-               cpcusb_delete(card);
-       else
-               wake_up_interruptible(card->chan->CPCWait_q);
-
-       up(&disconnect_sem);
-
-       CPCUsbCnt--;
-       info("USB-%d now disconnected", minor);
-}
-
-static int __init CPCUsb_Init(void)
-{
-       int result, i;
-
-       info(DRIVER_DESC " v" DRIVER_VERSION);
-       info("Build on " __DATE__ " at " __TIME__);
-
-       for (i = 0; i < CPC_USB_CARD_CNT; i++)
-               CPCUSB_Table[i] = 0;
-
-       /* register this driver with the USB subsystem */
-       result = usb_register(&cpcusb_driver);
-       if (result) {
-               err("usb_register failed. Error number %d", result);
-               return result;
-       }
-
-       procDir = proc_mkdir(CPC_USB_PROC_DIR, NULL);
-       if (!procDir) {
-               err("Could not create proc entry");
-       } else {
-               procEntry = create_proc_read_entry("info", 0444, procDir,
-                                                  cpcusb_proc_read_info,
-                                                  NULL);
-               if (!procEntry) {
-                       err("Could not create proc entry %s", CPC_USB_PROC_DIR "/info");
-                       remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-                       procDir = NULL;
-               }
-       }
-
-       return 0;
-}
-
-static void __exit CPCUsb_Exit(void)
-{
-       wait_event(rmmodWq, !atomic_read(&useCount));
-
-       /* deregister this driver with the USB subsystem */
-       usb_deregister(&cpcusb_driver);
-
-       if (procDir) {
-               if (procEntry)
-                       remove_proc_entry("info", procDir);
-               remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-       }
-}
-
-module_init(CPCUsb_Init);
-module_exit(CPCUsb_Exit);
diff --git a/drivers/staging/cpc-usb/cpc.h b/drivers/staging/cpc-usb/cpc.h
deleted file mode 100644 (file)
index ed8cb34..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * CPC CAN Interface Definitions
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-#ifndef CPC_HEADER
-#define CPC_HEADER
-
-// the maximum length of the union members within a CPC_MSG
-// this value can be defined by the customer, but has to be
-// >= 64 bytes
-// however, if not defined before, we set a length of 64 byte
-#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
-#undef CPC_MSG_LEN
-#define CPC_MSG_LEN 64
-#endif
-
-// check the operating system used
-#ifdef _WIN32 // running a Windows OS
-
-// define basic types on Windows platforms
-#ifdef _MSC_VER // Visual Studio
-       typedef unsigned __int8 u8;
-       typedef unsigned __int16 u16;
-       typedef unsigned __int32 u32;
-#else // Borland Compiler
-       typedef unsigned char u8;
-       typedef unsigned short u16;
-       typedef unsigned int u32;
-#endif
-       // on Windows OS we use a byte alignment of 1
-       #pragma pack(push, 1)
-
-       // set the calling conventions for the library function calls
-       #define CALL_CONV __stdcall
-#else
-       // Kernel headers already define this types
-       #ifndef __KERNEL__
-               // define basic types
-               typedef unsigned char u8;
-               typedef unsigned short u16;
-               typedef unsigned int u32;
-       #endif
-
-       // Linux does not use this calling convention
-       #define CALL_CONV
-#endif
-
-// Transmission of events from CPC interfaces to PC can be individually
-// controlled per event type. Default state is: don't transmit
-// Control values are constructed by bit-or of Subject and Action
-// and passed to CPC_Control()
-
-// Control-Values for CPC_Control() Command Subject Selection
-#define CONTR_CAN_Message 0x04
-#define CONTR_Busload    0x08
-#define        CONTR_CAN_State   0x0C
-#define        CONTR_SendAck     0x10
-#define        CONTR_Filter      0x14
-#define CONTR_CmdQueue    0x18 // reserved, do not use
-#define CONTR_BusError    0x1C
-
-// Control Command Actions
-#define CONTR_CONT_OFF    0
-#define CONTR_CONT_ON     1
-#define CONTR_SING_ON     2
-// CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
-// read as: transmit at least once
-
-// defines for confirmed request
-#define DO_NOT_CONFIRM 0
-#define DO_CONFIRM     1
-
-// event flags
-#define EVENT_READ 0x01
-#define EVENT_WRITE 0x02
-
-// Messages from CPC to PC contain a message object type field.
-// The following message types are sent by CPC and can be used in
-// handlers, others should be ignored.
-#define CPC_MSG_T_RESYNC        0 // Normally to be ignored
-#define CPC_MSG_T_CAN           1 // CAN data frame
-#define CPC_MSG_T_BUSLOAD       2 // Busload message
-#define CPC_MSG_T_STRING        3 // Normally to be ignored
-#define CPC_MSG_T_CONTI         4 // Normally to be ignored
-#define CPC_MSG_T_MEM           7 // Normally not to be handled
-#define        CPC_MSG_T_RTR           8 // CAN remote frame
-#define CPC_MSG_T_TXACK                9 // Send acknowledge
-#define CPC_MSG_T_POWERUP      10 // Power-up message
-#define        CPC_MSG_T_CMD_NO       11 // Normally to be ignored
-#define        CPC_MSG_T_CAN_PRMS     12 // Actual CAN parameters
-#define        CPC_MSG_T_ABORTED      13 // Command aborted message
-#define        CPC_MSG_T_CANSTATE     14 // CAN state message
-#define CPC_MSG_T_RESET        15 // used to reset CAN-Controller
-#define        CPC_MSG_T_XCAN         16 // XCAN data frame
-#define CPC_MSG_T_XRTR         17 // XCAN remote frame
-#define CPC_MSG_T_INFO         18 // information strings
-#define CPC_MSG_T_CONTROL      19 // used for control of interface/driver behaviour
-#define CPC_MSG_T_CONFIRM      20 // response type for confirmed requests
-#define CPC_MSG_T_OVERRUN      21 // response type for overrun conditions
-#define CPC_MSG_T_KEEPALIVE    22 // response type for keep alive conditions
-#define CPC_MSG_T_CANERROR     23 // response type for bus error conditions
-#define CPC_MSG_T_DISCONNECTED 24 // response type for a disconnected interface
-#define CPC_MSG_T_ERR_COUNTER  25 // RX/TX error counter of CAN controller
-
-#define CPC_MSG_T_FIRMWARE    100 // response type for USB firmware download
-
-// Messages from the PC to the CPC interface contain a command field
-// Most of the command types are wrapped by the library functions and have therefore
-// normally not to be used.
-// However, programmers who wish to circumvent the library and talk directly
-// to the drivers (mainly Linux programmers) can use the following
-// command types:
-
-#define CPC_CMD_T_CAN                 1        // CAN data frame
-#define CPC_CMD_T_CONTROL             3        // used for control of interface/driver behaviour
-#define        CPC_CMD_T_CAN_PRMS            6 // set CAN parameters
-#define        CPC_CMD_T_CLEARBUF            8 // clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead
-#define        CPC_CMD_T_INQ_CAN_PARMS      11 // inquire actual CAN parameters
-#define        CPC_CMD_T_FILTER_PRMS        12 // set filter parameter
-#define        CPC_CMD_T_RTR                13 // CAN remote frame
-#define        CPC_CMD_T_CANSTATE           14 // CAN state message
-#define        CPC_CMD_T_XCAN               15 // XCAN data frame
-#define CPC_CMD_T_XRTR               16        // XCAN remote frame
-#define CPC_CMD_T_RESET              17        // used to reset CAN-Controller
-#define CPC_CMD_T_INQ_INFO           18        // miscellanous information strings
-#define CPC_CMD_T_OPEN_CHAN          19        // open a channel
-#define CPC_CMD_T_CLOSE_CHAN         20        // close a channel
-#define CPC_CMD_T_CNTBUF             21        // this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead
-#define CPC_CMD_T_CAN_EXIT          200 // exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1)
-
-#define CPC_CMD_T_INQ_MSG_QUEUE_CNT  CPC_CMD_T_CNTBUF   // inquires the count of elements in the message queue
-#define CPC_CMD_T_INQ_ERR_COUNTER    25                        // request the CAN controllers error counter
-#define        CPC_CMD_T_CLEAR_MSG_QUEUE    CPC_CMD_T_CLEARBUF // clear CPC_MSG queue
-#define        CPC_CMD_T_CLEAR_CMD_QUEUE    28                 // clear CPC_CMD queue
-#define CPC_CMD_T_FIRMWARE          100                 // reserved, must not be used
-#define CPC_CMD_T_USB_RESET         101                 // reserved, must not be used
-#define CPC_CMD_T_WAIT_NOTIFY       102                 // reserved, must not be used
-#define CPC_CMD_T_WAIT_SETUP        103                 // reserved, must not be used
-#define        CPC_CMD_T_ABORT             255                 // Normally not to be used
-
-// definitions for CPC_MSG_T_INFO
-// information sources
-#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
-#define CPC_INFOMSG_T_INTERFACE      1
-#define CPC_INFOMSG_T_DRIVER         2
-#define CPC_INFOMSG_T_LIBRARY        3
-
-// information types
-#define CPC_INFOMSG_T_UNKNOWN_TYPE   0
-#define CPC_INFOMSG_T_VERSION        1
-#define CPC_INFOMSG_T_SERIAL         2
-
-// definitions for controller types
-#define PCA82C200   1 // Philips basic CAN controller, replaced by SJA1000
-#define SJA1000     2 // Philips basic CAN controller
-#define AN82527     3 // Intel full CAN controller
-#define M16C_BASIC  4 // M16C controller running in basic CAN (not full CAN) mode
-
-// channel open error codes
-#define CPC_ERR_NO_FREE_CHANNEL            -1  // no more free space within the channel array
-#define CPC_ERR_CHANNEL_ALREADY_OPEN       -2  // the channel is already open
-#define CPC_ERR_CHANNEL_NOT_ACTIVE         -3  // access to a channel not active failed
-#define CPC_ERR_NO_DRIVER_PRESENT          -4  // no driver at the location searched by the library
-#define CPC_ERR_NO_INIFILE_PRESENT         -5  // the library could not find the inifile
-#define CPC_ERR_WRONG_PARAMETERS           -6  // wrong parameters in the inifile
-#define CPC_ERR_NO_INTERFACE_PRESENT       -7  // 1. The specified interface is not connected
-                                               // 2. The interface (mostly CPC-USB) was disconnected upon operation
-#define CPC_ERR_NO_MATCHING_CHANNEL        -8  // the driver couldn't find a matching channel
-#define CPC_ERR_NO_BUFFER_AVAILABLE        -9  // the driver couldn't allocate buffer for messages
-#define CPC_ERR_NO_INTERRUPT               -10 // the requested interrupt couldn't be claimed
-#define CPC_ERR_NO_MATCHING_INTERFACE      -11 // no interface type related to this channel was found
-#define CPC_ERR_NO_RESOURCES               -12 // the requested resources could not be claimed
-#define CPC_ERR_SOCKET                     -13 // error concerning TCP sockets
-
-// init error codes
-#define CPC_ERR_WRONG_CONTROLLER_TYPE      -14 // wrong CAN controller type within initialization
-#define CPC_ERR_NO_RESET_MODE              -15 // the controller could not be set into reset mode
-#define CPC_ERR_NO_CAN_ACCESS              -16 // the CAN controller could not be accessed
-
-// transmit error codes
-#define CPC_ERR_CAN_WRONG_ID               -20 // the provided CAN id is too big
-#define CPC_ERR_CAN_WRONG_LENGTH           -21 // the provided CAN length is too long
-#define CPC_ERR_CAN_NO_TRANSMIT_BUF        -22 // the transmit buffer was occupied
-#define CPC_ERR_CAN_TRANSMIT_TIMEOUT       -23 // The message could not be sent within a
-                                               // specified time
-
-// other error codes
-#define CPC_ERR_SERVICE_NOT_SUPPORTED      -30 // the requested service is not supported by the interface
-#define CPC_ERR_IO_TRANSFER                -31 // a transmission error down to the driver occurred
-#define CPC_ERR_TRANSMISSION_FAILED        -32 // a transmission error down to the interface occurred
-#define CPC_ERR_TRANSMISSION_TIMEOUT       -33 // a timeout occurred within transmission to the interface
-#define CPC_ERR_OP_SYS_NOT_SUPPORTED       -35 // the operating system is not supported
-#define CPC_ERR_UNKNOWN                    -40 // an unknown error ocurred (mostly IOCTL errors)
-
-#define CPC_ERR_LOADING_DLL                -50 // the library 'cpcwin.dll' could not be loaded
-#define CPC_ERR_ASSIGNING_FUNCTION         -51 // the specified function could not be assigned
-#define CPC_ERR_DLL_INITIALIZATION         -52 // the DLL was not initialized correctly
-#define CPC_ERR_MISSING_LICFILE            -55 // the file containing the licenses does not exist
-#define CPC_ERR_MISSING_LICENSE            -56 // a required license was not found
-
-// CAN state bit values. Ignore any bits not listed
-#define CPC_CAN_STATE_BUSOFF     0x80
-#define CPC_CAN_STATE_ERROR      0x40
-
-// Mask to help ignore undefined bits
-#define CPC_CAN_STATE_MASK       0xc0
-
-// CAN-Message representation in a CPC_MSG
-// Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
-// or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
-typedef struct CPC_CAN_MSG {
-       u32 id;
-       u8 length;
-       u8 msg[8];
-} CPC_CAN_MSG_T;
-
-
-// representation of the CAN parameters for the PCA82C200 controller
-typedef struct CPC_PCA82C200_PARAMS {
-       u8 acc_code;    // Acceptance-code for receive, Standard: 0
-       u8 acc_mask;    // Acceptance-mask for receive, Standard: 0xff (everything)
-       u8 btr0;        // Bus-timing register 0
-       u8 btr1;        // Bus-timing register 1
-       u8 outp_contr;  // Output-control register
-} CPC_PCA82C200_PARAMS_T;
-
-// representation of the CAN parameters for the SJA1000 controller
-typedef struct CPC_SJA1000_PARAMS {
-       u8 mode;        // enables single or dual acceptance filtering
-       u8 acc_code0;   // Acceptance-code for receive, Standard: 0
-       u8 acc_code1;
-       u8 acc_code2;
-       u8 acc_code3;
-       u8 acc_mask0;   // Acceptance-mask for receive, Standard: 0xff (everything)
-       u8 acc_mask1;
-       u8 acc_mask2;
-       u8 acc_mask3;
-       u8 btr0;        // Bus-timing register 0
-       u8 btr1;        // Bus-timing register 1
-       u8 outp_contr;  // Output-control register
-} CPC_SJA1000_PARAMS_T;
-
-// representation of the CAN parameters for the M16C controller
-// in basic CAN mode (means no full CAN)
-typedef struct CPC_M16C_BASIC_PARAMS {
-       u8 con0;
-       u8 con1;
-       u8 ctlr0;
-       u8 ctlr1;
-       u8 clk;
-       u8 acc_std_code0;
-       u8 acc_std_code1;
-       u8 acc_ext_code0;
-       u8 acc_ext_code1;
-       u8 acc_ext_code2;
-       u8 acc_ext_code3;
-       u8 acc_std_mask0;
-       u8 acc_std_mask1;
-       u8 acc_ext_mask0;
-       u8 acc_ext_mask1;
-       u8 acc_ext_mask2;
-       u8 acc_ext_mask3;
-} CPC_M16C_BASIC_PARAMS_T;
-
-// CAN params message representation
-typedef struct CPC_CAN_PARAMS {
-       u8 cc_type;     // represents the controller type
-       union {
-               CPC_M16C_BASIC_PARAMS_T m16c_basic;
-               CPC_SJA1000_PARAMS_T sja1000;
-               CPC_PCA82C200_PARAMS_T pca82c200;
-       } cc_params;
-} CPC_CAN_PARAMS_T;
-
-// the following structures are slightly different for Windows and Linux
-// To be able to use the 'Select' mechanism with Linux the application
-// needs to know the devices file desciptor.
-// This mechanism is not implemented within Windows and the file descriptor
-// is therefore not needed
-#ifdef _WIN32
-
-// CAN init params message representation
-typedef struct CPC_INIT_PARAMS {
-       CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-#else// Linux
-
-// CHAN init params representation
-typedef struct CPC_CHAN_PARAMS {
-       int fd;
-} CPC_CHAN_PARAMS_T;
-
-// CAN init params message representation
-typedef struct CPC_INIT_PARAMS {
-       CPC_CHAN_PARAMS_T chanparams;
-       CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-#endif
-
-// structure for confirmed message handling
-typedef struct CPC_CONFIRM {
-       u8 result; // error code
-} CPC_CONFIRM_T;
-
-// structure for information requests
-typedef struct CPC_INFO {
-       u8 source;                 // interface, driver or library
-       u8 type;                   // version or serial number
-       char msg[CPC_MSG_LEN - 2]; // string holding the requested information
-} CPC_INFO_T;
-
-// OVERRUN ///////////////////////////////////////
-// In general two types of overrun may occur.
-// A hardware overrun, where the CAN controller
-// lost a message, because the interrupt was
-// not handled before the next messgae comes in.
-// Or a software overrun, where i.e. a received
-// message could not be stored in the CPC_MSG
-// buffer.
-
-// After a software overrun has occurred
-// we wait until we have CPC_OVR_GAP slots
-// free in the CPC_MSG buffer.
-#define CPC_OVR_GAP               10
-
-// Two types of software overrun may occur.
-// A received CAN message or a CAN state event
-// can cause an overrun.
-// Note: A CPC_CMD which would normally store
-// its result immediately in the CPC_MSG
-// queue may fail, because the message queue is full.
-// This will not generate an overrun message, but
-// will halt command execution, until this command
-// is able to store its message in the message queue.
-#define CPC_OVR_EVENT_CAN       0x01
-#define CPC_OVR_EVENT_CANSTATE  0x02
-#define CPC_OVR_EVENT_BUSERROR  0x04
-
-// If the CAN controller lost a message
-// we indicate it with the highest bit
-// set in the count field.
-#define CPC_OVR_HW              0x80
-
-// structure for overrun conditions
-typedef struct {
-       u8 event;
-       u8 count;
-} CPC_OVERRUN_T;
-
-// CAN errors ////////////////////////////////////
-// Each CAN controller type has different
-// registers to record errors.
-// Therefor a structure containing the specific
-// errors is set up for each controller here
-
-// SJA1000 error structure
-// see the SJA1000 datasheet for detailed
-// explanation of the registers
-typedef struct CPC_SJA1000_CAN_ERROR {
-       u8 ecc;   // error capture code register
-       u8 rxerr; // RX error counter register
-       u8 txerr; // TX error counter register
-} CPC_SJA1000_CAN_ERROR_T;
-
-// M16C error structure
-// see the M16C datasheet for detailed
-// explanation of the registers
-typedef struct CPC_M16C_CAN_ERROR {
-       u8 tbd; // to be defined
-} CPC_M16C_CAN_ERROR_T;
-
-// structure for CAN error conditions
-#define  CPC_CAN_ECODE_ERRFRAME   0x01
-typedef struct CPC_CAN_ERROR {
-       u8 ecode;
-       struct {
-               u8 cc_type; // CAN controller type
-               union {
-                       CPC_SJA1000_CAN_ERROR_T sja1000;
-                       CPC_M16C_CAN_ERROR_T m16c;
-               } regs;
-       } cc;
-} CPC_CAN_ERROR_T;
-
-// Structure containing RX/TX error counter.
-// This structure is used to request the
-// values of the CAN controllers TX and RX
-// error counter.
-typedef struct CPC_CAN_ERR_COUNTER {
-       u8 rx;
-       u8 tx;
-} CPC_CAN_ERR_COUNTER_T;
-
-// If this flag is set, transmissions from PC to CPC are protected against loss
-#define CPC_SECURE_TO_CPC      0x01
-
-// If this flag is set, transmissions from CPC to PC are protected against loss
-#define CPC_SECURE_TO_PC       0x02
-
-// If this flag is set, the CAN-transmit buffer is checked to be free before sending a message
-#define CPC_SECURE_SEND                0x04
-
-// If this flag is set, the transmission complete flag is checked
-// after sending a message
-// THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
-#define CPC_SECURE_TRANSMIT    0x08
-
-// main message type used between library and application
-typedef struct CPC_MSG {
-       u8 type;        // type of message
-       u8 length;      // length of data within union 'msg'
-       u8 msgid;       // confirmation handle
-       u32 ts_sec;     // timestamp in seconds
-       u32 ts_nsec;    // timestamp in nano seconds
-       union {
-               u8 generic[CPC_MSG_LEN];
-               CPC_CAN_MSG_T canmsg;
-               CPC_CAN_PARAMS_T canparams;
-               CPC_CONFIRM_T confirmation;
-               CPC_INFO_T info;
-               CPC_OVERRUN_T overrun;
-               CPC_CAN_ERROR_T error;
-               CPC_CAN_ERR_COUNTER_T err_counter;
-               u8 busload;
-               u8 canstate;
-       } msg;
-} CPC_MSG_T;
-
-#ifdef _WIN32
-#pragma pack(pop)              // reset the byte alignment
-#endif
-
-#endif                         // CPC_HEADER
diff --git a/drivers/staging/cpc-usb/cpc_int.h b/drivers/staging/cpc-usb/cpc_int.h
deleted file mode 100644 (file)
index a0d60c0..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * CPCLIB
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-#ifndef CPC_INT_H
-#define CPC_INT_H
-
-#include <linux/wait.h>
-
-#define CPC_MSG_BUF_CNT        1500
-
-#define CPC_PROC_DIR "driver/"
-
-#undef dbg
-#undef err
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
-
-/* Macros help using of our buffers */
-#define IsBufferFull(x)     (!(x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferEmpty(x)    ((x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
-#define ResetBuffer(x)      do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
-
-#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
-
-typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
-                                  unsigned char val);
-typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
-
-typedef struct CPC_CHAN {
-       void __iomem * canBase; // base address of SJA1000
-       chan_read_byte_t read_byte;     // CAN controller read access routine
-       chan_write_byte_t write_byte;   // CAN controller write access routine
-       CPC_MSG_T *buf;         // buffer for CPC msg
-       unsigned int iidx;
-       unsigned int oidx;
-       unsigned int WnR;
-       unsigned int minor;
-       unsigned int locked;
-       unsigned int irqDisabled;
-
-       unsigned char cpcCtrlCANMessage;
-       unsigned char cpcCtrlCANState;
-       unsigned char cpcCtrlBUSState;
-
-       unsigned char controllerType;
-
-       unsigned long ovrTimeSec;
-       unsigned long ovrTimeNSec;
-       unsigned long ovrLockedBuffer;
-       CPC_OVERRUN_T ovr;
-
-       /* for debugging only */
-       unsigned int handledIrqs;
-       unsigned int lostMessages;
-
-       unsigned int sentStdCan;
-       unsigned int sentExtCan;
-       unsigned int sentStdRtr;
-       unsigned int sentExtRtr;
-
-       unsigned int recvStdCan;
-       unsigned int recvExtCan;
-       unsigned int recvStdRtr;
-       unsigned int recvExtRtr;
-
-       wait_queue_head_t *CPCWait_q;
-
-       void *private;
-} CPC_CHAN_T;
-
-#endif
diff --git a/drivers/staging/cpc-usb/cpcusb.h b/drivers/staging/cpc-usb/cpcusb.h
deleted file mode 100644 (file)
index e5273dd..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Header for CPC-USB Driver ********************
- * Copyright 1999, 2000, 2001
- *
- * Company:  EMS Dr. Thomas Wuensche
- *           Sonnenhang 3
- *           85304 Ilmmuenster
- *           Phone: +49-8441-490260
- *           Fax:   +49-8441-81860
- *           email: support@ems-wuensche.com
- *           WWW:   www.ems-wuensche.com
- */
-
-#ifndef CPCUSB_H
-#define CPCUSB_H
-
-#undef err
-#undef dbg
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
-
-#define CPC_USB_CARD_CNT      4
-
-typedef struct CPC_USB_READ_URB {
-       unsigned char *buffer;  /* the buffer to send data */
-       size_t size;            /* the size of the send buffer */
-       struct urb *urb;        /* the urb used to send data */
-} CPC_USB_READ_URB_T;
-
-typedef struct CPC_USB_WRITE_URB {
-       unsigned char *buffer;  /* the buffer to send data */
-       size_t size;            /* the size of the send buffer */
-       struct urb *urb;        /* the urb used to send data */
-       atomic_t busy;          /* true if write urb is busy */
-       struct completion finished;     /* wait for the write to finish */
-} CPC_USB_WRITE_URB_T;
-
-#define CPC_USB_URB_CNT  10
-
-typedef struct CPC_USB {
-       struct usb_device *udev;        /* save off the usb device pointer */
-       struct usb_interface *interface;        /* the interface for this device */
-       unsigned char minor;    /* the starting minor number for this device */
-       unsigned char num_ports;        /* the number of ports this device has */
-       int num_intr_in;        /* number of interrupt in endpoints we have */
-       int num_bulk_in;        /* number of bulk in endpoints we have */
-       int num_bulk_out;       /* number of bulk out endpoints we have */
-
-       CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
-
-       unsigned char intr_in_buffer[4];        /* interrupt transfer buffer */
-       struct urb *intr_in_urb;        /* interrupt transfer urb */
-
-       CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
-
-       int open;               /* if the port is open or not */
-       int present;            /* if the device is not disconnected */
-       struct semaphore sem;   /* locks this structure */
-
-       int free_slots;         /* free send slots of CPC-USB */
-       int idx;
-
-       spinlock_t slock;
-
-       char serialNumber[128]; /* serial number */
-       int productId;          /* product id to differ between M16C and LPC2119 */
-       CPC_CHAN_T *chan;
-} CPC_USB_T;
-
-#define CPCTable               CPCUSB_Table
-
-#define CPC_DRIVER_VERSION "0.724"
-#define CPC_DRIVER_SERIAL  "not applicable"
-
-#define OBUF_SIZE 255          // 4096
-
-/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
-#define RD_EXPIRE 12           /* Number of attempts to wait X seconds */
-
-#define CPC_USB_BASE_MNR 0     /* CPC-USB start at minor 0  */
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c.h b/drivers/staging/cpc-usb/sja2m16c.h
deleted file mode 100644 (file)
index 654bd3f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _SJA2M16C_H
-#define _SJA2M16C_H
-
-#include "cpc.h"
-
-#define BAUDRATE_TOLERANCE_PERCENT     1
-#define SAMPLEPOINT_TOLERANCE_PERCENT  5
-#define SAMPLEPOINT_UPPER_LIMIT                88
-
-/* M16C parameters */
-struct FIELD_C0CONR {
-       unsigned int brp:4;
-       unsigned int sam:1;
-       unsigned int pr:3;
-       unsigned int dummy:8;
-};
-struct FIELD_C1CONR {
-       unsigned int ph1:3;
-       unsigned int ph2:3;
-       unsigned int sjw:2;
-       unsigned int dummy:8;
-};
-typedef union C0CONR {
-       unsigned char c0con;
-       struct FIELD_C0CONR bc0con;
-} C0CONR_T;
-typedef union C1CONR {
-       unsigned char c1con;
-       struct FIELD_C1CONR bc1con;
-} C1CONR_T;
-
-#define SJA_TSEG1      ((pParams->btr1 & 0x0f)+1)
-#define SJA_TSEG2      (((pParams->btr1 & 0x70)>>4)+1)
-#define SJA_BRP                ((pParams->btr0 & 0x3f)+1)
-#define SJA_SJW                ((pParams->btr0 & 0xc0)>>6)
-#define SJA_SAM                ((pParams->btr1 & 0x80)>>7)
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c_2.c b/drivers/staging/cpc-usb/sja2m16c_2.c
deleted file mode 100644 (file)
index bf0230f..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/****************************************************************************
-*
-*      Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
-*
-*                  - All rights reserved -
-*
-* This code is provided "as is" without warranty of any kind, either
-* expressed or implied, including but not limited to the liability
-* concerning the freedom from material defects, the fitness for parti-
-* cular purposes or the freedom of proprietary rights of third parties.
-*
-*****************************************************************************
-* Module name.: cpcusb
-*****************************************************************************
-* Include file: cpc.h
-*****************************************************************************
-* Project.....: Windows Driver Development Kit
-* Filename....: sja2m16c.cpp
-* Authors.....: (GU) Gerhard Uttenthaler
-*               (CS) Christian Schoett
-*****************************************************************************
-* Short descr.: converts baudrate between SJA1000 and M16C
-*****************************************************************************
-* Description.: handles the baudrate conversion from SJA1000 parameters to
-*               M16C parameters
-*****************************************************************************
-* Address     : EMS Dr. Thomas Wuensche
-*               Sonnenhang 3
-*               D-85304 Ilmmuenster
-*               Tel. : +49-8441-490260
-*               Fax. : +49-8441-81860
-*               email: support@ems-wuensche.com
-*****************************************************************************
-*                            History
-*****************************************************************************
-* Version  Date        Auth Remark
-*
-* 01.00    ??          GU   - initial release
-* 01.10    ??????????  CS   - adapted to fit into the USB Windows driver
-* 02.00    18.08.2004  GU   - improved the baudrate calculating algorithm
-*                           - implemented acceptance filtering
-* 02.10    10.09.2004  CS   - adapted to fit into the USB Windows driver
-*****************************************************************************
-*                            ToDo's
-*****************************************************************************
-*/
-
-/****************************************************************************/
-/*     I N C L U D E S
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include "cpc.h"
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/*********************************************************************/
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
-{
-       return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
-                                                           ph1 + 1 + ph2 +
-                                                           1);
-}
-
-
-/*********************************************************************/
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
-{
-       return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
-                                                 ph2 + 1);
-}
-
-
-/****************************************************************************
-* Function.....: SJA1000_TO_M16C_BASIC_Params
-*
-* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
-*                parameters based on the sample point and the error. In
-*                addition it converts the acceptance filter parameters to
-*                suit the M16C parameters
-*
-* Parameters...: None
-*
-* Return values: None
-*
-* Comments.....:
-*****************************************************************************
-*                History
-*****************************************************************************
-* 19.01.2005  CS   - modifed the conversion of SJA1000 filter params into
-*                    M16C params. Due to compatibility reasons with the
-*                    older 82C200 CAN controller the SJA1000
-****************************************************************************/
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
-{
-       int sjaBaudrate;
-       int sjaSamplepoint;
-       int *baudrate_error;    // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-       int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-       int baudrate_error_merk;
-       int clk, brp, pr, ph1, ph2;
-       int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
-       int index;
-       unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
-       unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
-       CPC_MSG_T * out;
-       C0CONR_T c0con;
-       C1CONR_T c1con;
-       int tmpAccCode;
-       int tmpAccMask;
-
-           // we have to convert the parameters into M16C parameters
-           CPC_SJA1000_PARAMS_T * pParams;
-
-           // check if the type is CAN parameters and if we have to convert the given params
-           if (in->type != CPC_CMD_T_CAN_PRMS
-               || in->msg.canparams.cc_type != SJA1000)
-               return 0;
-       pParams =
-           (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
-       acc_code0 = pParams->acc_code0;
-       acc_code1 = pParams->acc_code1;
-       acc_code2 = pParams->acc_code2;
-       acc_code3 = pParams->acc_code3;
-       acc_mask0 = pParams->acc_mask0;
-       acc_mask1 = pParams->acc_mask1;
-       acc_mask2 = pParams->acc_mask2;
-       acc_mask3 = pParams->acc_mask3;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-           info("acc_code0: %2.2Xh\n", acc_code0);
-       info("acc_code1: %2.2Xh\n", acc_code1);
-       info("acc_code2: %2.2Xh\n", acc_code2);
-       info("acc_code3: %2.2Xh\n", acc_code3);
-       info("acc_mask0: %2.2Xh\n", acc_mask0);
-       info("acc_mask1: %2.2Xh\n", acc_mask1);
-       info("acc_mask2: %2.2Xh\n", acc_mask2);
-       info("acc_mask3: %2.2Xh\n", acc_mask3);
-
-#endif /*  */
-           if (!
-                (baudrate_error =
-                 (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-               err("Could not allocate memory\n");
-               return -3;
-       }
-       if (!
-             (samplepoint_error =
-              (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-               err("Could not allocate memory\n");
-               vfree(baudrate_error);
-               return -3;
-       }
-       memset(baudrate_error, 0xff, sizeof(baudrate_error));
-       memset(samplepoint_error, 0xff, sizeof(baudrate_error));
-       sjaBaudrate =
-           16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
-       sjaSamplepoint =
-           100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
-       if (sjaBaudrate == 0) {
-               vfree(baudrate_error);
-               vfree(samplepoint_error);
-               return -2;
-       }
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-           info("\nStarting SJA CAN params\n");
-       info("-------------------------\n");
-       info("TS1     : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
-       info("BTR0    : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
-             pParams->btr1);
-       info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
-             sjaBaudrate % 1000);
-       info("Sample P: 0.%d\n", sjaSamplepoint);
-       info("\n");
-
-#endif /*  */
-           c0con.bc0con.sam = SJA_SAM;
-       c1con.bc1con.sjw = SJA_SJW;
-
-           // calculate errors for all baudrates
-           index = 0;
-       for (clk = 0; clk < 5; clk++) {
-               for (brp = 0; brp < 16; brp++) {
-                       for (pr = 0; pr < 8; pr++) {
-                               for (ph1 = 0; ph1 < 8; ph1++) {
-                                       for (ph2 = 0; ph2 < 8; ph2++) {
-                                               baudrate_error[index] =
-                                                   100 *
-                                                   abs(baudrate_m16c
-                                                       (clk, brp, pr, ph1,
-                                                        ph2) -
-                                                       sjaBaudrate) /
-                                                   sjaBaudrate;
-                                               samplepoint_error[index] =
-                                                   abs(samplepoint_m16c
-                                                       (brp, pr, ph1,
-                                                        ph2) -
-                                                       sjaSamplepoint);
-
-#if 0
-                                                   info
-                                                   ("Baudrate      : %d kBaud\n",
-                                                    baudrate_m16c(clk,
-                                                                  brp, pr,
-                                                                  ph1,
-                                                                  ph2));
-                                               info
-                                                   ("Baudrate Error: %d\n",
-                                                    baudrate_error
-                                                    [index]);
-                                               info
-                                                   ("Sample P Error: %d\n",
-                                                    samplepoint_error
-                                                    [index]);
-                                               info
-                                                   ("clk           : %d\n",
-                                                    clk);
-
-#endif /*  */
-                                                   index++;
-                                       }
-                               }
-                       }
-               }
-       }
-
-           // mark all baudrate_error entries which are outer limits
-           index = 0;
-       for (clk = 0; clk < 5; clk++) {
-               for (brp = 0; brp < 16; brp++) {
-                       for (pr = 0; pr < 8; pr++) {
-                               for (ph1 = 0; ph1 < 8; ph1++) {
-                                       for (ph2 = 0; ph2 < 8; ph2++) {
-                                               if ((baudrate_error[index]
-                                                     >
-                                                     BAUDRATE_TOLERANCE_PERCENT)
-                                                    ||
-                                                    (samplepoint_error
-                                                      [index] >
-                                                      SAMPLEPOINT_TOLERANCE_PERCENT)
-                                                    ||
-                                                    (samplepoint_m16c
-                                                      (brp, pr, ph1,
-                                                       ph2) >
-                                                      SAMPLEPOINT_UPPER_LIMIT))
-                                               {
-                                                       baudrate_error
-                                                           [index] = -1;
-                                               } else
-                                                   if (((1 + pr + 1 +
-                                                         ph1 + 1 + ph2 +
-                                                         1) < 8)
-                                                       ||
-                                                       ((1 + pr + 1 +
-                                                         ph1 + 1 + ph2 +
-                                                         1) > 25)) {
-                                                       baudrate_error
-                                                           [index] = -1;
-                                               }
-
-#if 0
-                                                   else {
-                                                       info
-                                                           ("Baudrate      : %d kBaud\n",
-                                                            baudrate_m16c
-                                                            (clk, brp, pr,
-                                                             ph1, ph2));
-                                                       info
-                                                           ("Baudrate Error: %d\n",
-                                                            baudrate_error
-                                                            [index]);
-                                                       info
-                                                           ("Sample P Error: %d\n",
-                                                            samplepoint_error
-                                                            [index]);
-                                               }
-
-#endif /*  */
-                                                   index++;
-                                       }
-                               }
-                       }
-               }
-       }
-
-           // find list of minimum of baudrate_error within unmarked entries
-           clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
-       baudrate_error_merk = 100;
-       index = 0;
-       for (clk = 0; clk < 5; clk++) {
-               for (brp = 0; brp < 16; brp++) {
-                       for (pr = 0; pr < 8; pr++) {
-                               for (ph1 = 0; ph1 < 8; ph1++) {
-                                       for (ph2 = 0; ph2 < 8; ph2++) {
-                                               if (baudrate_error[index]
-                                                    != -1) {
-                                                       if (baudrate_error
-                                                            [index] <
-                                                            baudrate_error_merk)
-                                                       {
-                                                               baudrate_error_merk
-                                                                   =
-                                                                   baudrate_error
-                                                                   [index];
-                                                               brp_merk =
-                                                                   brp;
-                                                               pr_merk =
-                                                                   pr;
-                                                               ph1_merk =
-                                                                   ph1;
-                                                               ph2_merk =
-                                                                   ph2;
-                                                               clk_merk =
-                                                                   clk;
-
-#if 0
-                                                                   info
-                                                                   ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
-                                                                    brp,
-                                                                    pr,
-                                                                    ph1,
-                                                                    ph2);
-                                                               info
-                                                                   ("Baudrate      : %d kBaud\n",
-                                                                    baudrate_m16c
-                                                                    (clk,
-                                                                     brp,
-                                                                     pr,
-                                                                     ph1,
-                                                                     ph2));
-                                                               info
-                                                                   ("Baudrate Error: %d\n",
-                                                                    baudrate_error
-                                                                    [index]);
-                                                               info
-                                                                   ("Sample P Error: %d\n",
-                                                                    samplepoint_error
-                                                                    [index]);
-
-#endif /*  */
-                                                       }
-                                               }
-                                               index++;
-                                       }
-                               }
-                       }
-               }
-       }
-       if (baudrate_error_merk == 100) {
-               info("ERROR: Could not convert CAN init parameter\n");
-               vfree(baudrate_error);
-               vfree(samplepoint_error);
-               return -1;
-       }
-
-           // setting m16c CAN parameter
-           c0con.bc0con.brp = brp_merk;
-       c0con.bc0con.pr = pr_merk;
-       c1con.bc1con.ph1 = ph1_merk;
-       c1con.bc1con.ph2 = ph2_merk;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-           info("\nResulting M16C CAN params\n");
-       info("-------------------------\n");
-       info("clk     : %2.2Xh\n", clk_merk);
-       info("ph1     : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
-             c1con.bc1con.ph2 + 1);
-       info("pr      : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
-             c0con.bc0con.brp + 1);
-       info("sjw     : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
-             c0con.bc0con.sam);
-       info("co1     : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
-       info("Baudrate: %d.%dBaud\n",
-              baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-                            c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
-              baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-                             c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
-       info("Sample P: 0.%d\n",
-             samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
-                              c1con.bc1con.ph1, c1con.bc1con.ph2));
-       info("\n");
-
-#endif /*  */
-           out = in;
-       out->type = 6;
-       out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
-       out->msg.canparams.cc_type = M16C_BASIC;
-       out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
-       out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
-       out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
-       out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
-       out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
-       out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-           acc_code0;
-       out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-           tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
-       out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-           (unsigned char) tmpAccCode;
-       out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
-           (unsigned char) (tmpAccCode >> 8);
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-           out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-           ~acc_mask0;
-       out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-           ~acc_mask1;
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-           tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
-
-//      info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
-           out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-           (unsigned char) ~tmpAccMask;
-       out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-           (unsigned char) ~(tmpAccMask >> 8);
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-           out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
-           (unsigned char) tmpAccCode;
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
-           (unsigned char) (tmpAccCode >> 8);
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
-           (unsigned char) ~tmpAccMask;
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
-           (unsigned char) ~(tmpAccMask >> 8);
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
-           ~acc_mask2;
-       out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
-           ~acc_mask3;
-       vfree(baudrate_error);
-       vfree(samplepoint_error);
-       return 0;
-}
-
-
index 878329cf4825f0db87b42ad67db6b6286b9d7183..ffe2663d49f2f1e15b4133efe1133d9119c57f20 100644 (file)
@@ -51,9 +51,10 @@ fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
 fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
                             e100/d102e_ucode.bin
 fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin
-fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis
+fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis cis/PCMLM28.cis
 fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis
 fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis
+fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis
 fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
 fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
                                      advansys/3550.bin advansys/38C0800.bin
index d9e3a94cb4df6803c8c00e608d0b24c62ba4fe3b..82db5256a4e5b24a9f76e6f27bacecdc07245708 100644 (file)
@@ -596,6 +596,7 @@ Found in hex form in kernel source.
 Driver: PCMCIA_PCNET - NE2000 compatible PCMCIA adapter
 
 File: cis/LA-PCM.cis
+      cis/PCMLM28.cis
 
 Licence: GPL
 
@@ -623,6 +624,17 @@ Originally developed by the pcmcia-cs project
 
 --------------------------------------------------------------------------
 
+Driver: SERIAL_8250_CS - Serial PCMCIA adapter
+
+File: cis/MT5634ZLX.cis
+      cis/RS-COM-2P.cis
+
+Licence: GPL
+
+Originally developed by the pcmcia-cs project
+
+--------------------------------------------------------------------------
+
 Driver: PCMCIA_SMC91C92 - SMC 91Cxx PCMCIA
 
 File: ositech/Xilinx7OD.bin
diff --git a/firmware/cis/MT5634ZLX.cis.ihex b/firmware/cis/MT5634ZLX.cis.ihex
new file mode 100644 (file)
index 0000000..72500b9
--- /dev/null
@@ -0,0 +1,11 @@
+:100000000101FF152204014D756C74695465636824
+:100010000050434D4349412035364B2044617461C3
+:10002000466178000000FF20040002010021020266
+:10003000001A05012780FF671B0FCF418B01550177
+:10004000550155AA60F80307281B08970108AA6004
+:10005000F802071B089F0108AA60E803071B08A70E
+:0B0060000108AA60E802071400FF007E
+:00000001FF
+#
+# Replacement CIS for Multitech MT5634ZLX modems
+#
diff --git a/firmware/cis/PCMLM28.cis.ihex b/firmware/cis/PCMLM28.cis.ihex
new file mode 100644 (file)
index 0000000..ffdfe85
--- /dev/null
@@ -0,0 +1,18 @@
+:1000000001030000FF151504014C494E4B53595391
+:100010000050434D4C4D3238000000FF2004430196
+:10002000ABC0210200001A05012FF803031B10E4E6
+:1000300001190155E06100031FF8020730FFFF1BA3
+:100040000BA50108E06120031FF802071B0BA601A6
+:1000500008E06140031FF802071B0BA70108E061DD
+:1000600060031FF802071B0BA80108E06100031FD3
+:10007000E803071B0BA90108E06120031FE8030741
+:100080001B0BAA0108E06140031FE803071B0BAB31
+:100090000108E06160031FE803071B0BAC0108E0E7
+:1000A0006100031FE802071B0BAD0108E06120039C
+:1000B0001FE802071B0BAE0108E06140031FE802C6
+:1000C000071B0BAF0108E06160031FE80207140083
+:0200D000FF002F
+:00000001FF
+#
+# The on-card CIS says it is MFC-compliant, but it is not
+#
diff --git a/firmware/cis/RS-COM-2P.cis.ihex b/firmware/cis/RS-COM-2P.cis.ihex
new file mode 100644 (file)
index 0000000..0801ca5
--- /dev/null
@@ -0,0 +1,10 @@
+:1000000001030000FF1516040150434D4349410010
+:1000100052532D434F4D203250000000FF21020269
+:10002000011A0501030001011B0EC18118AA61E834
+:100030000307E8020730B89E1B0B820108AA615033
+:1000400002075802071B0B830108AA6160020768B8
+:0600500002071400FF008E
+:00000001FF
+#
+# Replacement CIS for dual-serial-port IO card
+#
index 7609365577f1b88df0322f17fd6cd5cfaddcdc3d..5cb86c307f5d791298ae0add65bcd1f98dd781fb 100644 (file)
@@ -21,4 +21,111 @@ extern struct key_type key_type_rxrpc;
 
 extern struct key *rxrpc_get_null_key(const char *);
 
+/*
+ * RxRPC key for Kerberos IV (type-2 security)
+ */
+struct rxkad_key {
+       u32     vice_id;
+       u32     start;                  /* time at which ticket starts */
+       u32     expiry;                 /* time at which ticket expires */
+       u32     kvno;                   /* key version number */
+       u8      primary_flag;           /* T if key for primary cell for this user */
+       u16     ticket_len;             /* length of ticket[] */
+       u8      session_key[8];         /* DES session key */
+       u8      ticket[0];              /* the encrypted ticket */
+};
+
+/*
+ * Kerberos 5 principal
+ *     name/name/name@realm
+ */
+struct krb5_principal {
+       u8      n_name_parts;           /* N of parts of the name part of the principal */
+       char    **name_parts;           /* parts of the name part of the principal */
+       char    *realm;                 /* parts of the realm part of the principal */
+};
+
+/*
+ * Kerberos 5 tagged data
+ */
+struct krb5_tagged_data {
+       /* for tag value, see /usr/include/krb5/krb5.h
+        * - KRB5_AUTHDATA_* for auth data
+        * - 
+        */
+       s32             tag;
+       u32             data_len;
+       u8              *data;
+};
+
+/*
+ * RxRPC key for Kerberos V (type-5 security)
+ */
+struct rxk5_key {
+       u64                     authtime;       /* time at which auth token generated */
+       u64                     starttime;      /* time at which auth token starts */
+       u64                     endtime;        /* time at which auth token expired */
+       u64                     renew_till;     /* time to which auth token can be renewed */
+       s32                     is_skey;        /* T if ticket is encrypted in another ticket's
+                                                * skey */
+       s32                     flags;          /* mask of TKT_FLG_* bits (krb5/krb5.h) */
+       struct krb5_principal   client;         /* client principal name */
+       struct krb5_principal   server;         /* server principal name */
+       u16                     ticket_len;     /* length of ticket */
+       u16                     ticket2_len;    /* length of second ticket */
+       u8                      n_authdata;     /* number of authorisation data elements */
+       u8                      n_addresses;    /* number of addresses */
+       struct krb5_tagged_data session;        /* session data; tag is enctype */
+       struct krb5_tagged_data *addresses;     /* addresses */
+       u8                      *ticket;        /* krb5 ticket */
+       u8                      *ticket2;       /* second krb5 ticket, if related to ticket (via
+                                                * DUPLICATE-SKEY or ENC-TKT-IN-SKEY) */
+       struct krb5_tagged_data *authdata;      /* authorisation data */
+};
+
+/*
+ * list of tokens attached to an rxrpc key
+ */
+struct rxrpc_key_token {
+       u16     security_index;         /* RxRPC header security index */
+       struct rxrpc_key_token *next;   /* the next token in the list */
+       union {
+               struct rxkad_key *kad;
+               struct rxk5_key *k5;
+       };
+};
+
+/*
+ * structure of raw payloads passed to add_key() or instantiate key
+ */
+struct rxrpc_key_data_v1 {
+       u32             kif_version;            /* 1 */
+       u16             security_index;
+       u16             ticket_length;
+       u32             expiry;                 /* time_t */
+       u32             kvno;
+       u8              session_key[8];
+       u8              ticket[0];
+};
+
+/*
+ * AF_RXRPC key payload derived from XDR format
+ * - based on openafs-1.4.10/src/auth/afs_token.xg
+ */
+#define AFSTOKEN_LENGTH_MAX            16384   /* max payload size */
+#define AFSTOKEN_STRING_MAX            256     /* max small string length */
+#define AFSTOKEN_DATA_MAX              64      /* max small data length */
+#define AFSTOKEN_CELL_MAX              64      /* max cellname length */
+#define AFSTOKEN_MAX                   8       /* max tokens per payload */
+#define AFSTOKEN_BDATALN_MAX           16384   /* max big data length */
+#define AFSTOKEN_RK_TIX_MAX            12000   /* max RxKAD ticket size */
+#define AFSTOKEN_GK_KEY_MAX            64      /* max GSSAPI key size */
+#define AFSTOKEN_GK_TOKEN_MAX          16384   /* max GSSAPI token size */
+#define AFSTOKEN_K5_COMPONENTS_MAX     16      /* max K5 components */
+#define AFSTOKEN_K5_NAME_MAX           128     /* max K5 name length */
+#define AFSTOKEN_K5_REALM_MAX          64      /* max K5 realm name length */
+#define AFSTOKEN_K5_TIX_MAX            16384   /* max K5 ticket size */
+#define AFSTOKEN_K5_ADDRESSES_MAX      16      /* max K5 addresses */
+#define AFSTOKEN_K5_AUTHDATA_MAX       16      /* max K5 pieces of auth data */
+
 #endif /* _KEYS_RXRPC_TYPE_H */
index 92fbd8cbd68fc87032a77b739b24d4f2d63f7084..fe158e0e20e6a5b7957d78925c9ed2a044f0f557 100644 (file)
@@ -233,6 +233,8 @@ extern void ip_mc_init_dev(struct in_device *);
 extern void ip_mc_destroy_dev(struct in_device *);
 extern void ip_mc_up(struct in_device *);
 extern void ip_mc_down(struct in_device *);
+extern void ip_mc_unmap(struct in_device *);
+extern void ip_mc_remap(struct in_device *);
 extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
 extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
 extern void ip_mc_rejoin_group(struct ip_mc_list *im);
index 4fc2ffd527f9386e613afe1e54a552268a491eb5..9040a10584f7fe0b11ae5012d42e3cf5bec9fcf2 100644 (file)
@@ -57,6 +57,7 @@ typedef enum {
 #include <linux/random.h>
 #include <linux/wait.h>
 #include <linux/fcntl.h>       /* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/kmemcheck.h>
 
 struct poll_table_struct;
 struct pipe_inode_info;
@@ -127,7 +128,11 @@ enum sock_shutdown_cmd {
  */
 struct socket {
        socket_state            state;
+
+       kmemcheck_bitfield_begin(type);
        short                   type;
+       kmemcheck_bitfield_end(type);
+
        unsigned long           flags;
        /*
         * Please keep fasync_list & wait fields in the same cache line
index 65ee1929b2b1672a7cef0ca6b81af3ecca89a8bb..f46db6c7a734876274cf1487851aedef8f706748 100644 (file)
@@ -1873,7 +1873,8 @@ extern void               __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct
 extern int             dev_set_promiscuity(struct net_device *dev, int inc);
 extern int             dev_set_allmulti(struct net_device *dev, int inc);
 extern void            netdev_state_change(struct net_device *dev);
-extern void            netdev_bonding_change(struct net_device *dev);
+extern void            netdev_bonding_change(struct net_device *dev,
+                                             unsigned long event);
 extern void            netdev_features_change(struct net_device *dev);
 /* Load a device via the kmod */
 extern void            dev_load(struct net *net, const char *name);
index 0fbecbbe8e9e950b39f0b45b916c960e39acd4c8..080f6ba9e73a35063a8b0b6ae8a797b6a9b107da 100644 (file)
@@ -176,12 +176,16 @@ struct netlink_skb_parms
 #define NETLINK_CREDS(skb)     (&NETLINK_CB((skb)).creds)
 
 
+extern void netlink_table_grab(void);
+extern void netlink_table_ungrab(void);
+
 extern struct sock *netlink_kernel_create(struct net *net,
                                          int unit,unsigned int groups,
                                          void (*input)(struct sk_buff *skb),
                                          struct mutex *cb_mutex,
                                          struct module *module);
 extern void netlink_kernel_release(struct sock *sk);
+extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
 extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
index 81bc252dc8ac35d9ed7fbe877308f52ae59eb623..44428d247dbe6e3b52e9b71798eff99735ae4319 100644 (file)
@@ -199,6 +199,8 @@ static inline int notifier_to_errno(int ret)
 #define NETDEV_FEAT_CHANGE     0x000B
 #define NETDEV_BONDING_FAILOVER 0x000C
 #define NETDEV_PRE_UP          0x000D
+#define NETDEV_BONDING_OLDTYPE  0x000E
+#define NETDEV_BONDING_NEWTYPE  0x000F
 
 #define SYS_DOWN       0x0001  /* Notify of system down */
 #define SYS_RESTART    SYS_DOWN
index f7b826b565c721bfbd823cc485bbfd41f787e332..a53915cd5581d7c7b9c21f334d3a01f093c0a1b4 100644 (file)
@@ -58,5 +58,12 @@ struct sockaddr_rxrpc {
 #define RXRPC_SECURITY_AUTH    1       /* authenticated packets */
 #define RXRPC_SECURITY_ENCRYPT 2       /* encrypted packets */
 
+/*
+ * RxRPC security indices
+ */
+#define RXRPC_SECURITY_NONE    0       /* no security protocol */
+#define RXRPC_SECURITY_RXKAD   2       /* kaserver or kerberos 4 */
+#define RXRPC_SECURITY_RXGK    4       /* gssapi-based */
+#define RXRPC_SECURITY_RXK5    5       /* kerberos 5 */
 
 #endif /* _LINUX_RXRPC_H */
index bb69e256cd16d25b5ead7ddc64b2d581a84069a9..f8147305205980c1b0e6f6cf2b0545625e0efa79 100644 (file)
@@ -89,6 +89,7 @@ struct driver_info {
 #define FLAG_FRAMING_AX 0x0040         /* AX88772/178 packets */
 #define FLAG_WLAN      0x0080          /* use "wlan%d" names */
 #define FLAG_AVOID_UNLINK_URBS 0x0100  /* don't unlink urbs at usbnet_stop() */
+#define FLAG_SEND_ZLP  0x0200          /* hw requires ZLPs are sent */
 
 
        /* init device ... can sleep, or cause probe() failure */
index 7b55ab215a649a3c62f6f860300198e0f1587e26..0f7c37825fc146ae6a8ceee0ce269af3b4ef65eb 100644 (file)
@@ -143,6 +143,8 @@ extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr
 extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
 extern void ipv6_mc_up(struct inet6_dev *idev);
 extern void ipv6_mc_down(struct inet6_dev *idev);
+extern void ipv6_mc_unmap(struct inet6_dev *idev);
+extern void ipv6_mc_remap(struct inet6_dev *idev);
 extern void ipv6_mc_init_dev(struct inet6_dev *idev);
 extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
 extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
index 1089d5aabd4990f8b028e6fb3c7db8f82195950d..60249e51b6691354f70e5ffe00137f39c7371a4e 100644 (file)
@@ -94,21 +94,20 @@ struct inet_protosw {
 #define INET_PROTOSW_PERMANENT 0x02  /* Permanent protocols are unremovable. */
 #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
 
-extern struct net_protocol *inet_protocol_base;
-extern struct net_protocol *inet_protos[MAX_INET_PROTOS];
+extern const struct net_protocol *inet_protos[MAX_INET_PROTOS];
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
+extern const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
 #endif
 
-extern int     inet_add_protocol(struct net_protocol *prot, unsigned char num);
-extern int     inet_del_protocol(struct net_protocol *prot, unsigned char num);
+extern int     inet_add_protocol(const struct net_protocol *prot, unsigned char num);
+extern int     inet_del_protocol(const struct net_protocol *prot, unsigned char num);
 extern void    inet_register_protosw(struct inet_protosw *p);
 extern void    inet_unregister_protosw(struct inet_protosw *p);
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-extern int     inet6_add_protocol(struct inet6_protocol *prot, unsigned char num);
-extern int     inet6_del_protocol(struct inet6_protocol *prot, unsigned char num);
+extern int     inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
+extern int     inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
 extern int     inet6_register_protosw(struct inet_protosw *p);
 extern void    inet6_unregister_protosw(struct inet_protosw *p);
 #endif
index 88eb9de095de21006ed26fd84db96ca7f58c3b38..c33180dd42b4916e9cb6b73544b757b71755aecb 100644 (file)
@@ -81,7 +81,7 @@ struct Qdisc
 struct Qdisc_class_ops
 {
        /* Child qdisc manipulation */
-       unsigned int            (*select_queue)(struct Qdisc *, struct tcmsg *);
+       struct netdev_queue *   (*select_queue)(struct Qdisc *, struct tcmsg *);
        int                     (*graft)(struct Qdisc *, unsigned long cl,
                                        struct Qdisc *, struct Qdisc **);
        struct Qdisc *          (*leaf)(struct Qdisc *, unsigned long cl);
index b71a446d58f6c6a74b50ebb9d2ff5d1b8c55b13f..56b76027b85eeb4c7e4de930750e9584f6326489 100644 (file)
@@ -793,6 +793,13 @@ static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
        return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
 }
 
+#define TCP_INFINITE_SSTHRESH  0x7fffffff
+
+static inline bool tcp_in_initial_slowstart(const struct tcp_sock *tp)
+{
+       return tp->snd_ssthresh >= TCP_INFINITE_SSTHRESH;
+}
+
 /* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
  * The exception is rate halving phase, when cwnd is decreasing towards
  * ssthresh.
index 68320f6b07b51341218296ac170c6a9536a3a420..44e5936118d2fc0174537238bfa75ba951e305e9 100644 (file)
@@ -49,6 +49,7 @@ cond_syscall(sys_sendmsg);
 cond_syscall(compat_sys_sendmsg);
 cond_syscall(sys_recvmsg);
 cond_syscall(compat_sys_recvmsg);
+cond_syscall(compat_sys_recvfrom);
 cond_syscall(sys_socketcall);
 cond_syscall(sys_futex);
 cond_syscall(compat_sys_futex);
index cb8a112030bba9ba0522b56dca4d6c3bec2a8986..a1941f8d205f5b55337692fdd84b42f510599708 100644 (file)
@@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
        return p;
 }
 
-static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
+static char *ip6_compressed_string(char *p, const char *addr)
 {
        int i;
        int j;
@@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
        u8 hi;
        u8 lo;
        bool needcolon = false;
-       bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr);
+       bool useIPv4;
+       struct in6_addr in6;
+
+       memcpy(&in6, addr, sizeof(struct in6_addr));
+
+       useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
 
        memset(zerolength, 0, sizeof(zerolength));
 
@@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
        /* find position of longest 0 run */
        for (i = 0; i < range; i++) {
                for (j = i; j < range; j++) {
-                       if (addr->s6_addr16[j] != 0)
+                       if (in6.s6_addr16[j] != 0)
                                break;
                        zerolength[i]++;
                }
@@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
                        needcolon = false;
                }
                /* hex u16 without leading 0s */
-               word = ntohs(addr->s6_addr16[i]);
+               word = ntohs(in6.s6_addr16[i]);
                hi = word >> 8;
                lo = word & 0xff;
                if (hi) {
@@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
        if (useIPv4) {
                if (needcolon)
                        *p++ = ':';
-               p = ip4_string(p, &addr->s6_addr[12], false);
+               p = ip4_string(p, &in6.s6_addr[12], false);
        }
 
        *p = '\0';
        return p;
 }
 
-static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt)
+static char *ip6_string(char *p, const char *addr, const char *fmt)
 {
        int i;
        for (i = 0; i < 8; i++) {
-               p = pack_hex_byte(p, addr->s6_addr[2 * i]);
-               p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]);
+               p = pack_hex_byte(p, *addr++);
+               p = pack_hex_byte(p, *addr++);
                if (fmt[0] == 'I' && i != 7)
                        *p++ = ':';
        }
@@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
        char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
 
        if (fmt[0] == 'I' && fmt[2] == 'c')
-               ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr);
+               ip6_compressed_string(ip6_addr, addr);
        else
-               ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt);
+               ip6_string(ip6_addr, addr, fmt);
 
        return string(buf, end, ip6_addr, spec);
 }
index 4a6ff2ba4d071f459c7f6da04bc991da5a606ac8..b1a4290996b511ebc644e86ab9b7aeb693e74db8 100644 (file)
@@ -1372,7 +1372,7 @@ static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
 
        if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP)
                return NET_RX_DROP;
-       return NET_XMIT_SUCCESS;
+       return NET_RX_SUCCESS;
 free_it:
        kfree_skb(skb);
 drop:
index da0f64f82b5771f65ada62e157b042119ade99b8..d6b1b054e29454fde8e92d5e4c137f2fce52971f 100644 (file)
@@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
                ax25_info.n2count   = ax25->n2count;
                ax25_info.state     = ax25->state;
-               ax25_info.rcv_q     = sk_wmem_alloc_get(sk);
-               ax25_info.snd_q     = sk_rmem_alloc_get(sk);
+               ax25_info.rcv_q     = sk_rmem_alloc_get(sk);
+               ax25_info.snd_q     = sk_wmem_alloc_get(sk);
                ax25_info.vs        = ax25->vs;
                ax25_info.vr        = ax25->vr;
                ax25_info.va        = ax25->va;
index ef1c43a2ed564a4dbcecd92b35dbe4fc702b86b9..606832115674147be25d49bea7f12ce293b9bc2a 100644 (file)
@@ -199,6 +199,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
  * @skb: pointer to socket buffer with CAN frame in data section
  * @loop: loopback for listeners on local CAN sockets (recommended default!)
  *
+ * Due to the loopback this routine must not be called from hardirq context.
+ *
  * Return:
  *  0 on success
  *  -ENETDOWN when the selected interface is down
@@ -278,7 +280,7 @@ int can_send(struct sk_buff *skb, int loop)
        }
 
        if (newskb)
-               netif_rx(newskb);
+               netif_rx_ni(newskb);
 
        /* update statistics */
        can_stats.tx_frames++;
index 84945470ab38cc073ff71eb8dac14ad653c9cad0..560c8c9c03ab3ccfef96bfd1eed5fc195c4b1a75 100644 (file)
@@ -1017,9 +1017,9 @@ void netdev_state_change(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_state_change);
 
-void netdev_bonding_change(struct net_device *dev)
+void netdev_bonding_change(struct net_device *dev, unsigned long event)
 {
-       call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, dev);
+       call_netdevice_notifiers(event, dev);
 }
 EXPORT_SYMBOL(netdev_bonding_change);
 
index 4b5db44970aa23c8e8032542d0f5d55ea6bed415..8408398cd44e814cece7b9ec92615b1c615d32bd 100644 (file)
@@ -66,9 +66,9 @@ config IP_DCCP_CCID3_RTO
            A value of 0 disables this feature by enforcing the value specified
            in RFC 3448. The following values have been suggested as bounds for
            experimental use:
-               * 16-20ms to match the typical multimedia inter-frame interval
-               * 100ms as a reasonable compromise [default]
-               * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4)
+               * 16-20ms to match the typical multimedia inter-frame interval
+               * 100ms as a reasonable compromise [default]
+               * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4)
 
            The default of 100ms is a compromise between a large value for
            efficient DCCP implementations, and a small value to avoid disrupting
index d235294ace23b640960999a8dd2be995d82f1193..e8cf99e880b0c765bf2c983b7118939f2c0977a5 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/ccid2.c
- *
  *  Copyright (c) 2005, 2006 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
  *
  *  Changes to meet Linux coding standards, and DCCP infrastructure fixes.
index 2c94ca0290107b1d464cb9938101969d4b135763..326ac90fb9091bb40871cbf12c763aeec2398eb8 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/ccid2.h
- *
  *  Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -40,14 +38,14 @@ struct ccid2_seq {
 #define CCID2_SEQBUF_LEN 1024
 #define CCID2_SEQBUF_MAX 128
 
-/** struct ccid2_hc_tx_sock - CCID2 TX half connection
- *
+/**
+ * struct ccid2_hc_tx_sock - CCID2 TX half connection
  * @ccid2hctx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5
  * @ccid2hctx_packets_acked - Ack counter for deriving cwnd growth (RFC 3465)
  * @ccid2hctx_lastrtt -time RTT was last measured
  * @ccid2hctx_rpseq - last consecutive seqno
  * @ccid2hctx_rpdupack - dupacks since rpseq
-*/
+ */
 struct ccid2_hc_tx_sock {
        u32                     ccid2hctx_cwnd;
        u32                     ccid2hctx_ssthresh;
index f596ce149c3c00a18ae4213d7f5c9e6d86bd1df6..34dcc798c457b4f11b058f43303f4af231361b2b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/ccid3.c
- *
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
@@ -750,7 +748,8 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
        return 0;
 }
 
-/** ccid3_first_li  -  Implements [RFC 3448, 6.3.1]
+/**
+ * ccid3_first_li  -  Implements [RFC 5348, 6.3.1]
  *
  * Determine the length of the first loss interval via inverse lookup.
  * Assume that X_recv can be computed by the throughput equation
index 49ca32bd7e79d608592aaae0371545ff246ab013..e5a24414384634b0d0a38e8da57a987286c72801 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/ccid3.h
- *
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *
@@ -75,8 +73,8 @@ enum ccid3_hc_tx_states {
        TFRC_SSTATE_TERM,
 };
 
-/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
- *
+/**
+ * struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
  * @ccid3hctx_x - Current sending rate in 64 * bytes per second
  * @ccid3hctx_x_recv - Receive rate    in 64 * bytes per second
  * @ccid3hctx_x_calc - Calculated rate in bytes per second
@@ -119,9 +117,9 @@ struct ccid3_hc_tx_sock {
 
 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
 {
-    struct ccid3_hc_tx_sock *hctx = ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
-    BUG_ON(hctx == NULL);
-    return hctx;
+       struct ccid3_hc_tx_sock *hctx = ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
+       BUG_ON(hctx == NULL);
+       return hctx;
 }
 
 /* TFRC receiver states */
@@ -131,22 +129,22 @@ enum ccid3_hc_rx_states {
        TFRC_RSTATE_TERM    = 127,
 };
 
-/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket
- *
- *  @ccid3hcrx_x_recv  -  Receiver estimate of send rate (RFC 3448 4.3)
- *  @ccid3hcrx_rtt  -  Receiver estimate of rtt (non-standard)
- *  @ccid3hcrx_p  -  Current loss event rate (RFC 3448 5.4)
- *  @ccid3hcrx_last_counter  -  Tracks window counter (RFC 4342, 8.1)
- *  @ccid3hcrx_state  -  Receiver state, one of %ccid3_hc_rx_states
- *  @ccid3hcrx_bytes_recv  -  Total sum of DCCP payload bytes
- *  @ccid3hcrx_x_recv  -  Receiver estimate of send rate (RFC 3448, sec. 4.3)
- *  @ccid3hcrx_rtt  -  Receiver estimate of RTT
- *  @ccid3hcrx_tstamp_last_feedback  -  Time at which last feedback was sent
- *  @ccid3hcrx_tstamp_last_ack  -  Time at which last feedback was sent
- *  @ccid3hcrx_hist  -  Packet history (loss detection + RTT sampling)
- *  @ccid3hcrx_li_hist  -  Loss Interval database
- *  @ccid3hcrx_s  -  Received packet size in bytes
- *  @ccid3hcrx_pinv  -  Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
+/**
+ * struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket
+ * @ccid3hcrx_x_recv  -  Receiver estimate of send rate (RFC 3448 4.3)
+ * @ccid3hcrx_rtt  -  Receiver estimate of rtt (non-standard)
+ * @ccid3hcrx_p  -  Current loss event rate (RFC 3448 5.4)
+ * @ccid3hcrx_last_counter  -  Tracks window counter (RFC 4342, 8.1)
+ * @ccid3hcrx_state  -  Receiver state, one of %ccid3_hc_rx_states
+ * @ccid3hcrx_bytes_recv  -  Total sum of DCCP payload bytes
+ * @ccid3hcrx_x_recv  -  Receiver estimate of send rate (RFC 3448, sec. 4.3)
+ * @ccid3hcrx_rtt  -  Receiver estimate of RTT
+ * @ccid3hcrx_tstamp_last_feedback  -  Time at which last feedback was sent
+ * @ccid3hcrx_tstamp_last_ack  -  Time at which last feedback was sent
+ * @ccid3hcrx_hist  -  Packet history (loss detection + RTT sampling)
+ * @ccid3hcrx_li_hist  -  Loss Interval database
+ * @ccid3hcrx_s  -  Received packet size in bytes
+ * @ccid3hcrx_pinv  -  Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
  */
 struct ccid3_hc_rx_sock {
        u8                              ccid3hcrx_last_counter:4;
@@ -163,9 +161,9 @@ struct ccid3_hc_rx_sock {
 
 static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
 {
-    struct ccid3_hc_rx_sock *hcrx = ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
-    BUG_ON(hcrx == NULL);
-    return hcrx;
+       struct ccid3_hc_rx_sock *hcrx = ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
+       BUG_ON(hcrx == NULL);
+       return hcrx;
 }
 
 #endif /* _DCCP_CCID3_H_ */
index 4d1e401272646c88789c9c0beb537718b3260708..8fc3cbf79071fdc7dc904d154864b007f9768a42 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/lib/loss_interval.c
- *
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
@@ -21,7 +19,7 @@ static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
 /* implements LIFO semantics on the array */
 static inline u8 LIH_INDEX(const u8 ctr)
 {
-       return (LIH_SIZE - 1 - (ctr % LIH_SIZE));
+       return LIH_SIZE - 1 - (ctr % LIH_SIZE);
 }
 
 /* the `counter' index always points at the next entry to be populated */
@@ -129,7 +127,8 @@ static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
                (cur->li_is_closed || SUB16(new_loss->tfrchrx_ccval, cur->li_ccval) > 4);
 }
 
-/** tfrc_lh_interval_add  -  Insert new record into the Loss Interval database
+/**
+ * tfrc_lh_interval_add  -  Insert new record into the Loss Interval database
  * @lh:                   Loss Interval database
  * @rh:                   Receive history containing a fresh loss event
  * @calc_first_li: Caller-dependent routine to compute length of first interval
index 246018a3b269f7a714f121eeb18cedbf832fee20..d1d2f5383b7d3d7cec533be0d7b8d939ebe492dd 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _DCCP_LI_HIST_
 #define _DCCP_LI_HIST_
 /*
- *  net/dccp/ccids/lib/loss_interval.h
- *
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
index b7785b3581ec2ee5a747ec3975d00496f6a42183..3a4f414e94a0051bf66429739680d3d5ee8fb432 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/packet_history.c
- *
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *
@@ -128,7 +126,7 @@ u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
 
 
 /*
- *     Receiver History Routines
+ *     Receiver History Routines
  */
 static struct kmem_cache *tfrc_rx_hist_slab;
 
index 461cc91cce88aecee60a32c8ab496de770192ad5..7df6c52999999a4c76c99802d0dbcf54a8654211 100644 (file)
@@ -70,7 +70,6 @@ struct tfrc_rx_hist_entry {
 
 /**
  * tfrc_rx_hist  -  RX history structure for TFRC-based protocols
- *
  * @ring:              Packet history for RTT sampling and loss detection
  * @loss_count:                Number of entries in circular history
  * @loss_start:                Movable index (for loss detection)
index e9720b14327536192b72fa282d97fa439eeb0a99..01bb48e96c2ed0b6955c50ee348817e1415f61fd 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _TFRC_H_
 #define _TFRC_H_
 /*
- *  net/dccp/ccids/lib/tfrc.h
- *
  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
@@ -32,7 +30,7 @@ extern int tfrc_debug;
 /* integer-arithmetic divisions of type (a * 1000000)/b */
 static inline u64 scaled_div(u64 a, u64 b)
 {
-       BUG_ON(b==0);
+       BUG_ON(b == 0);
        return div64_u64(a * 1000000, b);
 }
 
index c5d3a9e5a5a46ee59e5665087df31fcaeb0986ff..22ca1cf0eb5503fe6ed2db69172771f0e207b182 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  net/dccp/ccids/lib/tfrc_equation.c
- *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
     }
 
   With the given configuration, we have, with M = TFRC_CALC_X_ARRSIZE-1,
-    lookup[0][0]  =  g(1000000/(M+1))           =  1000000 * f(0.2%)
-    lookup[M][0]  =  g(1000000)                         =  1000000 * f(100%)
-    lookup[0][1]  =  g(TFRC_SMALLEST_P)                  = 1000000 * f(0.01%)
-    lookup[M][1]  =  g(TFRC_CALC_X_SPLIT)       =  1000000 * f(5%)
+    lookup[0][0]  =  g(1000000/(M+1))          = 1000000 * f(0.2%)
+    lookup[M][0]  =  g(1000000)                        = 1000000 * f(100%)
+    lookup[0][1]  =  g(TFRC_SMALLEST_P)                = 1000000 * f(0.01%)
+    lookup[M][1]  =  g(TFRC_CALC_X_SPLIT)      = 1000000 * f(5%)
 
   In summary, the two columns represent f(p) for the following ranges:
     * The first column is for   0.002  <= p <= 1.0
@@ -610,11 +608,10 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small)
 
 /**
  * tfrc_calc_x - Calculate the send rate as per section 3.1 of RFC3448
- *
- *  @s: packet size          in bytes
- *  @R: RTT                  scaled by 1000000   (i.e., microseconds)
- *  @p: loss ratio estimate  scaled by 1000000
- *  Returns X_calc           in bytes per second (not scaled).
+ * @s: packet size          in bytes
+ * @R: RTT                  scaled by 1000000   (i.e., microseconds)
+ * @p: loss ratio estimate  scaled by 1000000
+ * Returns X_calc           in bytes per second (not scaled).
  */
 u32 tfrc_calc_x(u16 s, u32 R, u32 p)
 {
@@ -630,17 +627,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
                return ~0U;
        }
 
-       if (p <= TFRC_CALC_X_SPLIT)             {     /* 0.0000 < p <= 0.05   */
+       if (p <= TFRC_CALC_X_SPLIT)             {     /* 0.0000 < p <= 0.05   */
                if (p < TFRC_SMALLEST_P) {            /* 0.0000 < p <  0.0001 */
                        DCCP_WARN("Value of p (%d) below resolution. "
                                  "Substituting %d\n", p, TFRC_SMALLEST_P);
                        index = 0;
-               } else                                /* 0.0001 <= p <= 0.05  */
+               } else                                /* 0.0001 <= p <= 0.05  */
                        index =  p/TFRC_SMALLEST_P - 1;
 
                f = tfrc_calc_x_lookup[index][1];
 
-       } else {                                      /* 0.05   <  p <= 1.00  */
+       } else {                                      /* 0.05   <  p <= 1.00  */
                index = p/(1000000/TFRC_CALC_X_ARRSIZE) - 1;
 
                f = tfrc_calc_x_lookup[index][0];
@@ -661,7 +658,6 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
 
 /**
  *  tfrc_calc_x_reverse_lookup  -  try to find p given f(p)
- *
  *  @fvalue: function value to match, scaled by 1000000
  *  Returns closest match for p, also scaled by 1000000
  */
index d01c00de1ad0b2487a86a918b9e4916c71308c58..7302e1498d46e1b89381bc6dc834335a59a892cc 100644 (file)
@@ -948,7 +948,7 @@ static struct proto dccp_v4_prot = {
 #endif
 };
 
-static struct net_protocol dccp_v4_protocol = {
+static const struct net_protocol dccp_v4_protocol = {
        .handler        = dccp_v4_rcv,
        .err_handler    = dccp_v4_err,
        .no_policy      = 1,
index 64f011cc44916f99f37f9ab8279f055870d19b3a..e48ca5d45658468176bb60c8cbb53a587feea72d 100644 (file)
@@ -1152,13 +1152,13 @@ static struct proto dccp_v6_prot = {
 #endif
 };
 
-static struct inet6_protocol dccp_v6_protocol = {
+static const struct inet6_protocol dccp_v6_protocol = {
        .handler        = dccp_v6_rcv,
        .err_handler    = dccp_v6_err,
        .flags          = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
 };
 
-static struct proto_ops inet6_dccp_ops = {
+static const struct proto_ops inet6_dccp_ops = {
        .family            = PF_INET6,
        .owner             = THIS_MODULE,
        .release           = inet6_release,
index 77ae6852b93d11b3e1c9e5ad4f143d1188d281c9..51593a48f2ddae396a97395239ca7f7c1aad5859 100644 (file)
@@ -414,7 +414,7 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
 }
 
 static int dgram_setsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int __user optlen)
+                   char __user *optval, int optlen)
 {
        struct dgram_sock *ro = dgram_sk(sk);
        int val;
index 2106ecbf0308eb3101291d6f6f8f807567952413..ca767bde17a455a2f426e57dc1e2dc1db471c4a4 100644 (file)
@@ -35,6 +35,7 @@
 #include <net/ieee802154_netdev.h>
 
 static unsigned int ieee802154_seq_num;
+static DEFINE_SPINLOCK(ieee802154_seq_lock);
 
 static struct genl_family ieee802154_coordinator_family = {
        .id             = GENL_ID_GENERATE,
@@ -57,12 +58,15 @@ static struct sk_buff *ieee802154_nl_create(int flags, u8 req)
 {
        void *hdr;
        struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+       unsigned long f;
 
        if (!msg)
                return NULL;
 
+       spin_lock_irqsave(&ieee802154_seq_lock, f);
        hdr = genlmsg_put(msg, 0, ieee802154_seq_num++,
                        &ieee802154_coordinator_family, flags, req);
+       spin_unlock_irqrestore(&ieee802154_seq_lock, f);
        if (!hdr) {
                nlmsg_free(msg);
                return NULL;
index 4681501aae930928a76ecaaf02dbdc6cd68d892c..13198859982e64baf80b97463af6e0b70bc75a50 100644 (file)
@@ -244,7 +244,7 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
 }
 
 static int raw_setsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int __user optlen)
+                   char __user *optval, int optlen)
 {
        return -EOPNOTSUPP;
 }
index 6c30a73f03f58e0c96f07e1292809b176c09f595..58c4b0f7c4aae333e5767e331b84bebbe4845bd0 100644 (file)
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(build_ehash_secret);
 static inline int inet_netns_ok(struct net *net, int protocol)
 {
        int hash;
-       struct net_protocol *ipprot;
+       const struct net_protocol *ipprot;
 
        if (net_eq(net, &init_net))
                return 1;
@@ -1162,7 +1162,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);
 static int inet_gso_send_check(struct sk_buff *skb)
 {
        struct iphdr *iph;
-       struct net_protocol *ops;
+       const struct net_protocol *ops;
        int proto;
        int ihl;
        int err = -EINVAL;
@@ -1198,7 +1198,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        struct iphdr *iph;
-       struct net_protocol *ops;
+       const struct net_protocol *ops;
        int proto;
        int ihl;
        int id;
@@ -1265,7 +1265,7 @@ out:
 static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
-       struct net_protocol *ops;
+       const struct net_protocol *ops;
        struct sk_buff **pp = NULL;
        struct sk_buff *p;
        struct iphdr *iph;
@@ -1342,7 +1342,7 @@ out:
 
 static int inet_gro_complete(struct sk_buff *skb)
 {
-       struct net_protocol *ops;
+       const struct net_protocol *ops;
        struct iphdr *iph = ip_hdr(skb);
        int proto = iph->protocol & (MAX_INET_PROTOS - 1);
        int err = -ENOSYS;
@@ -1427,13 +1427,13 @@ void snmp_mib_free(void *ptr[2])
 EXPORT_SYMBOL_GPL(snmp_mib_free);
 
 #ifdef CONFIG_IP_MULTICAST
-static struct net_protocol igmp_protocol = {
+static const struct net_protocol igmp_protocol = {
        .handler =      igmp_rcv,
        .netns_ok =     1,
 };
 #endif
 
-static struct net_protocol tcp_protocol = {
+static const struct net_protocol tcp_protocol = {
        .handler =      tcp_v4_rcv,
        .err_handler =  tcp_v4_err,
        .gso_send_check = tcp_v4_gso_send_check,
@@ -1444,7 +1444,7 @@ static struct net_protocol tcp_protocol = {
        .netns_ok =     1,
 };
 
-static struct net_protocol udp_protocol = {
+static const struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
        .gso_send_check = udp4_ufo_send_check,
@@ -1453,7 +1453,7 @@ static struct net_protocol udp_protocol = {
        .netns_ok =     1,
 };
 
-static struct net_protocol icmp_protocol = {
+static const struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
        .no_policy =    1,
        .netns_ok =     1,
index e878e494296ef948958bb0ff845a145742cb90ec..5c662703eb1e9cf917df97b41e024c52b946be38 100644 (file)
@@ -311,7 +311,7 @@ static const struct xfrm_type ah_type =
        .output         = ah_output
 };
 
-static struct net_protocol ah4_protocol = {
+static const struct net_protocol ah4_protocol = {
        .handler        =       xfrm4_rcv,
        .err_handler    =       ah4_err,
        .no_policy      =       1,
index 3863c3a4223f45f84167b9a50c708049822f1ce4..07336c6201f0dede9e93c75f811b64af7d8cc853 100644 (file)
@@ -1087,6 +1087,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        case NETDEV_DOWN:
                ip_mc_down(in_dev);
                break;
+       case NETDEV_BONDING_OLDTYPE:
+               ip_mc_unmap(in_dev);
+               break;
+       case NETDEV_BONDING_NEWTYPE:
+               ip_mc_remap(in_dev);
+               break;
        case NETDEV_CHANGEMTU:
                if (inetdev_valid_mtu(dev->mtu))
                        break;
index 18bb383ea39354c52ceb593a78f462d839fba5e4..12f7287e902dcac7614cfb8375c1788e15e006cc 100644 (file)
@@ -615,7 +615,7 @@ static const struct xfrm_type esp_type =
        .output         = esp_output
 };
 
-static struct net_protocol esp4_protocol = {
+static const struct net_protocol esp4_protocol = {
        .handler        =       xfrm4_rcv,
        .err_handler    =       esp4_err,
        .no_policy      =       1,
index 97c410e8438895664a9abdbbf5670b26af01dffa..5bc13fe816d125780d1b5518560dda663817e80e 100644 (file)
@@ -655,7 +655,7 @@ static void icmp_unreach(struct sk_buff *skb)
        struct iphdr *iph;
        struct icmphdr *icmph;
        int hash, protocol;
-       struct net_protocol *ipprot;
+       const struct net_protocol *ipprot;
        u32 info = 0;
        struct net *net;
 
index 01b4284ed694fc86540da28253e159625acc0f5e..d41e5de79a822b658b8bde74c3d88f96524f2166 100644 (file)
@@ -1298,6 +1298,28 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
        }
 }
 
+/* Device changing type */
+
+void ip_mc_unmap(struct in_device *in_dev)
+{
+       struct ip_mc_list *i;
+
+       ASSERT_RTNL();
+
+       for (i = in_dev->mc_list; i; i = i->next)
+               igmp_group_dropped(i);
+}
+
+void ip_mc_remap(struct in_device *in_dev)
+{
+       struct ip_mc_list *i;
+
+       ASSERT_RTNL();
+
+       for (i = in_dev->mc_list; i; i = i->next)
+               igmp_group_added(i);
+}
+
 /* Device going down */
 
 void ip_mc_down(struct in_device *in_dev)
index 533afaadefd4a25a09b8fd511f43032a57a87238..d9645c94a0678fd76f64ffbbaf40f63184a7e878 100644 (file)
@@ -1288,7 +1288,7 @@ static void ipgre_fb_tunnel_init(struct net_device *dev)
 }
 
 
-static struct net_protocol ipgre_protocol = {
+static const struct net_protocol ipgre_protocol = {
        .handler        =       ipgre_rcv,
        .err_handler    =       ipgre_err,
        .netns_ok       =       1,
index db46b4b5b2b9429db018b1abcadaf26d92316048..6c98b43badf4e1d770a3f28df87e6674dd963c42 100644 (file)
@@ -202,7 +202,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
        {
                int protocol = ip_hdr(skb)->protocol;
                int hash, raw;
-               struct net_protocol *ipprot;
+               const struct net_protocol *ipprot;
 
        resubmit:
                raw = raw_local_deliver(skb, protocol);
index 3262ce06294c314a85bfcb4d643e4d3ec020b4e4..38fbf04150ae7ec60ccafa1a4bd740995fb13427 100644 (file)
@@ -146,7 +146,7 @@ static const struct xfrm_type ipcomp_type = {
        .output         = ipcomp_output
 };
 
-static struct net_protocol ipcomp4_protocol = {
+static const struct net_protocol ipcomp4_protocol = {
        .handler        =       xfrm4_rcv,
        .err_handler    =       ipcomp4_err,
        .no_policy      =       1,
index 65d421cf5bc717754353f443a62aa856605f6347..c43ec2d51ce21dcb8666785f52bbd5417d868a0e 100644 (file)
@@ -99,10 +99,6 @@ static int ipmr_cache_report(struct net *net,
                             struct sk_buff *pkt, vifi_t vifi, int assert);
 static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm);
 
-#ifdef CONFIG_IP_PIMSM_V2
-static struct net_protocol pim_protocol;
-#endif
-
 static struct timer_list ipmr_expire_timer;
 
 /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
@@ -1945,7 +1941,7 @@ static const struct file_operations ipmr_mfc_fops = {
 #endif
 
 #ifdef CONFIG_IP_PIMSM_V2
-static struct net_protocol pim_protocol = {
+static const struct net_protocol pim_protocol = {
        .handler        =       pim_rcv,
        .netns_ok       =       1,
 };
index a2e5fc0a15e15eff1abdecba3d94c870fc2054ec..542f22fc98b3948f80ba1f30027106ddeb882047 100644 (file)
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 
-struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp;
+const struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp;
 static DEFINE_SPINLOCK(inet_proto_lock);
 
 /*
  *     Add a protocol handler to the hash tables
  */
 
-int inet_add_protocol(struct net_protocol *prot, unsigned char protocol)
+int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        int hash, ret;
 
@@ -57,7 +57,7 @@ int inet_add_protocol(struct net_protocol *prot, unsigned char protocol)
  *     Remove a protocol from the hash tables.
  */
 
-int inet_del_protocol(struct net_protocol *prot, unsigned char protocol)
+int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        int hash, ret;
 
index edeea060db4466691f5206679e67b6bd77c28044..19a0612b8a207c3d92aba38e25ce8f01c5e73f72 100644 (file)
@@ -2012,7 +2012,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->snd_cwnd = 2;
        icsk->icsk_probes_out = 0;
        tp->packets_out = 0;
-       tp->snd_ssthresh = 0x7fffffff;
+       tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
        tp->snd_cwnd_cnt = 0;
        tp->bytes_acked = 0;
        tcp_set_ca_state(sk, TCP_CA_Open);
index af6d6fa00db124f091df1559a31c0bb95d07b8ac..d86784be7ab3d0160122cdd42f071cffaae82351 100644 (file)
@@ -761,7 +761,7 @@ void tcp_update_metrics(struct sock *sk)
                        set_dst_metric_rtt(dst, RTAX_RTTVAR, var);
                }
 
-               if (tp->snd_ssthresh >= 0xFFFF) {
+               if (tcp_in_initial_slowstart(tp)) {
                        /* Slow start still did not finish. */
                        if (dst_metric(dst, RTAX_SSTHRESH) &&
                            !dst_metric_locked(dst, RTAX_SSTHRESH) &&
index 0543561da9992125fa2afe24312c78ddf6f88cbb..7cda24b53f610482dbee6de501334991aba030cb 100644 (file)
@@ -1808,7 +1808,7 @@ static int tcp_v4_init_sock(struct sock *sk)
        /* See draft-stevens-tcpca-spec-01 for discussion of the
         * initialization of these values.
         */
-       tp->snd_ssthresh = 0x7fffffff;  /* Infinity */
+       tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
        tp->snd_cwnd_clamp = ~0;
        tp->mss_cache = 536;
 
@@ -2284,7 +2284,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
                jiffies_to_clock_t(icsk->icsk_ack.ato),
                (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                tp->snd_cwnd,
-               tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh,
+               tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh,
                len);
 }
 
index e48c37d74d77a5fd7a4312d338c5a2020f40ddc9..624c3c9b3c2bbe33a37f53b105d041b08ce490ef 100644 (file)
@@ -363,7 +363,7 @@ void tcp_twsk_destructor(struct sock *sk)
 #ifdef CONFIG_TCP_MD5SIG
        struct tcp_timewait_sock *twsk = tcp_twsk(sk);
        if (twsk->tw_md5_keylen)
-               tcp_put_md5sig_pool();
+               tcp_free_md5sig_pool();
 #endif
 }
 
@@ -410,7 +410,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->retrans_out = 0;
                newtp->sacked_out = 0;
                newtp->fackets_out = 0;
-               newtp->snd_ssthresh = 0x7fffffff;
+               newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
 
                /* So many TCP implementations out there (incorrectly) count the
                 * initial SYN frame in their delayed-ACK and congestion control
index cb1f0e83830b408871139ca9a809b5320ea809b7..3959e0ca456a09ce2457e120e2244358629ee428 100644 (file)
@@ -132,7 +132,7 @@ static void tunnel64_err(struct sk_buff *skb, u32 info)
 }
 #endif
 
-static struct net_protocol tunnel4_protocol = {
+static const struct net_protocol tunnel4_protocol = {
        .handler        =       tunnel4_rcv,
        .err_handler    =       tunnel4_err,
        .no_policy      =       1,
@@ -140,7 +140,7 @@ static struct net_protocol tunnel4_protocol = {
 };
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static struct net_protocol tunnel64_protocol = {
+static const struct net_protocol tunnel64_protocol = {
        .handler        =       tunnel64_rcv,
        .err_handler    =       tunnel64_err,
        .no_policy      =       1,
index c784891cb7e57b3f037b26f858c714bfc9614a33..95248d7f75ec43f9952f78d24b3ff1beaaa3e331 100644 (file)
@@ -25,7 +25,7 @@ static void udplite_err(struct sk_buff *skb, u32 info)
        __udp4_lib_err(skb, info, &udplite_table);
 }
 
-static struct net_protocol udplite_protocol = {
+static const struct net_protocol udplite_protocol = {
        .handler        = udplite_rcv,
        .err_handler    = udplite_err,
        .no_policy      = 1,
index c9b369034a4006562343825f2e73381e4aaf39f8..55f486d89c88eeb1d3e1409cd115cf996c9a8b07 100644 (file)
@@ -137,6 +137,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock);
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
 
+static void addrconf_bonding_change(struct net_device *dev,
+                                   unsigned long event);
 static int addrconf_ifdown(struct net_device *dev, int how);
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
@@ -1405,8 +1407,8 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
        struct inet6_dev *idev = ifp->idev;
 
        if (net_ratelimit())
-               printk(KERN_INFO "%s: IPv6 duplicate address detected!\n",
-                       ifp->idev->dev->name);
+               printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n",
+                       ifp->idev->dev->name, &ifp->addr);
 
        if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
                struct in6_addr addr;
@@ -2582,6 +2584,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                                return notifier_from_errno(err);
                }
                break;
+       case NETDEV_BONDING_OLDTYPE:
+       case NETDEV_BONDING_NEWTYPE:
+               addrconf_bonding_change(dev, event);
+               break;
        }
 
        return NOTIFY_OK;
@@ -2595,6 +2601,19 @@ static struct notifier_block ipv6_dev_notf = {
        .priority = 0
 };
 
+static void addrconf_bonding_change(struct net_device *dev, unsigned long event)
+{
+       struct inet6_dev *idev;
+       ASSERT_RTNL();
+
+       idev = __in6_dev_get(dev);
+
+       if (event == NETDEV_BONDING_NEWTYPE)
+               ipv6_mc_remap(idev);
+       else if (event == NETDEV_BONDING_OLDTYPE)
+               ipv6_mc_unmap(idev);
+}
+
 static int addrconf_ifdown(struct net_device *dev, int how)
 {
        struct inet6_dev *idev;
index a123a328aeb317e3ab0cfa5c4906f3240105a5eb..e127a32f9540fecfaee5de6332ca1be64ce6541f 100644 (file)
@@ -710,7 +710,7 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
 
 static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
 {
-       struct inet6_protocol *ops = NULL;
+       const struct inet6_protocol *ops = NULL;
 
        for (;;) {
                struct ipv6_opt_hdr *opth;
@@ -745,7 +745,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
 static int ipv6_gso_send_check(struct sk_buff *skb)
 {
        struct ipv6hdr *ipv6h;
-       struct inet6_protocol *ops;
+       const struct inet6_protocol *ops;
        int err = -EINVAL;
 
        if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
@@ -773,7 +773,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        struct ipv6hdr *ipv6h;
-       struct inet6_protocol *ops;
+       const struct inet6_protocol *ops;
        int proto;
        struct frag_hdr *fptr;
        unsigned int unfrag_ip6hlen;
@@ -840,7 +840,7 @@ struct ipv6_gro_cb {
 static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
-       struct inet6_protocol *ops;
+       const struct inet6_protocol *ops;
        struct sk_buff **pp = NULL;
        struct sk_buff *p;
        struct ipv6hdr *iph;
@@ -926,7 +926,7 @@ out:
 
 static int ipv6_gro_complete(struct sk_buff *skb)
 {
-       struct inet6_protocol *ops;
+       const struct inet6_protocol *ops;
        struct ipv6hdr *iph = ipv6_hdr(skb);
        int err = -ENOSYS;
 
index 86f42a288c4bb487237ffa6da9944e20d0456efb..c1589e2f1dc9f57d975b94a4a086121ff6bdac92 100644 (file)
@@ -527,7 +527,7 @@ static const struct xfrm_type ah6_type =
        .hdr_offset     = xfrm6_find_1stfragopt,
 };
 
-static struct inet6_protocol ah6_protocol = {
+static const struct inet6_protocol ah6_protocol = {
        .handler        =       xfrm6_rcv,
        .err_handler    =       ah6_err,
        .flags          =       INET6_PROTO_NOPOLICY,
index 678bb95b1525716f2120db6abe3332a7c4e5edab..af597c73ebe9b6bc53f5ae0eb4c91a268a66e47d 100644 (file)
@@ -558,7 +558,7 @@ static const struct xfrm_type esp6_type =
        .hdr_offset     = xfrm6_find_1stfragopt,
 };
 
-static struct inet6_protocol esp6_protocol = {
+static const struct inet6_protocol esp6_protocol = {
        .handler        =       xfrm6_rcv,
        .err_handler    =       esp6_err,
        .flags          =       INET6_PROTO_NOPOLICY,
index 4aae658e55016999c25640c41d2624eb49884903..df159fffe4bca2c373bb1d78bf03959244019bd2 100644 (file)
@@ -500,17 +500,17 @@ unknown_rh:
        return -1;
 }
 
-static struct inet6_protocol rthdr_protocol = {
+static const struct inet6_protocol rthdr_protocol = {
        .handler        =       ipv6_rthdr_rcv,
        .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 };
 
-static struct inet6_protocol destopt_protocol = {
+static const struct inet6_protocol destopt_protocol = {
        .handler        =       ipv6_destopt_rcv,
        .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 };
 
-static struct inet6_protocol nodata_protocol = {
+static const struct inet6_protocol nodata_protocol = {
        .handler        =       dst_discard,
        .flags          =       INET6_PROTO_NOPOLICY,
 };
index e2325f6a05fbd4e9a0d154ca5ddcf6386296760e..f23ebbec0631792407f6ea82827a572027050401 100644 (file)
@@ -86,7 +86,7 @@ static inline struct sock *icmpv6_sk(struct net *net)
 
 static int icmpv6_rcv(struct sk_buff *skb);
 
-static struct inet6_protocol icmpv6_protocol = {
+static const struct inet6_protocol icmpv6_protocol = {
        .handler        =       icmpv6_rcv,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
@@ -583,7 +583,7 @@ out:
 
 static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
 {
-       struct inet6_protocol *ipprot;
+       const struct inet6_protocol *ipprot;
        int inner_offset;
        int hash;
        u8 nexthdr;
index 2d9cbaa67edb7232f6c992e66b8ece1d6d6bafd7..237e2dba6e944772e27e908188d7531e03744b7d 100644 (file)
@@ -159,7 +159,7 @@ drop:
 
 static int ip6_input_finish(struct sk_buff *skb)
 {
-       struct inet6_protocol *ipprot;
+       const struct inet6_protocol *ipprot;
        unsigned int nhoff;
        int nexthdr, raw;
        u8 hash;
index 5c8d73730c75d68dcdb050a5607fa073e1e7e40b..3907510c2ce3e17f21fa9b2d5f151d18edb28f6e 100644 (file)
@@ -83,10 +83,6 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt,
 static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
 static void mroute_clean_tables(struct net *net);
 
-#ifdef CONFIG_IPV6_PIMSM_V2
-static struct inet6_protocol pim6_protocol;
-#endif
-
 static struct timer_list ipmr_expire_timer;
 
 
@@ -410,7 +406,7 @@ static int pim6_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static struct inet6_protocol pim6_protocol = {
+static const struct inet6_protocol pim6_protocol = {
        .handler        =       pim6_rcv,
 };
 
index 79c172f1ff012d6b7f577ea20febae037ec96dad..2f2a5ca2c8786599560f7328d64401f837ab5e38 100644 (file)
@@ -178,7 +178,7 @@ static const struct xfrm_type ipcomp6_type =
        .hdr_offset     = xfrm6_find_1stfragopt,
 };
 
-static struct inet6_protocol ipcomp6_protocol =
+static const struct inet6_protocol ipcomp6_protocol =
 {
        .handler        = xfrm6_rcv,
        .err_handler    = ipcomp6_err,
index 71c3dacec1ed008c7f291e4aef0b7e6d55fe1c5e..f9fcf690bd5d60781f7c9c1d9e152eafb6712367 100644 (file)
@@ -2249,6 +2249,25 @@ static void igmp6_timer_handler(unsigned long data)
        ma_put(ma);
 }
 
+/* Device changing type */
+
+void ipv6_mc_unmap(struct inet6_dev *idev)
+{
+       struct ifmcaddr6 *i;
+
+       /* Install multicast list, except for all-nodes (already installed) */
+
+       read_lock_bh(&idev->lock);
+       for (i = idev->mc_list; i; i = i->next)
+               igmp6_group_dropped(i);
+       read_unlock_bh(&idev->lock);
+}
+
+void ipv6_mc_remap(struct inet6_dev *idev)
+{
+       ipv6_mc_up(idev);
+}
+
 /* Device going down */
 
 void ipv6_mc_down(struct inet6_dev *idev)
index 568864f722ca5cb92a704c836463572dceaa4b32..1fa3468f0f323782413c1931258c61aa9130f450 100644 (file)
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 
-struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
+const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
 static DEFINE_SPINLOCK(inet6_proto_lock);
 
 
-int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol)
+int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
        int ret, hash = protocol & (MAX_INET_PROTOS - 1);
 
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(inet6_add_protocol);
  *     Remove a protocol from the hash tables.
  */
 
-int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol)
+int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
        int ret, hash = protocol & (MAX_INET_PROTOS - 1);
 
index 2642a41a853518bc6405f6934554bdbaad58c875..da5bd0ed83df251a4a5340f382fc1639c2fa9a72 100644 (file)
@@ -627,7 +627,7 @@ fail_hdr:
        return -1;
 }
 
-static struct inet6_protocol frag_protocol =
+static const struct inet6_protocol frag_protocol =
 {
        .handler        =       ipv6_frag_rcv,
        .flags          =       INET6_PROTO_NOPOLICY,
index 9ccfef3455605d1c629c92aaa2f1346c556800a9..77aecbe8ff6caf261c04700d6bea889bb2221a7e 100644 (file)
@@ -481,7 +481,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 
        pref = rinfo->route_pref;
        if (pref == ICMPV6_ROUTER_PREF_INVALID)
-               pref = ICMPV6_ROUTER_PREF_MEDIUM;
+               return -EINVAL;
 
        lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ);
 
index 3aae0f217d611234a9673ea0fcc7671e46ec6aeb..21d100b68b190dd7d88510f6924713567e20bded 100644 (file)
@@ -1846,7 +1846,7 @@ static int tcp_v6_init_sock(struct sock *sk)
        /* See draft-stevens-tcpca-spec-01 for discussion of the
         * initialization of these values.
         */
-       tp->snd_ssthresh = 0x7fffffff;
+       tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
        tp->snd_cwnd_clamp = ~0;
        tp->mss_cache = 536;
 
@@ -1969,7 +1969,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   jiffies_to_clock_t(icsk->icsk_rto),
                   jiffies_to_clock_t(icsk->icsk_ack.ato),
                   (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
-                  tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
+                  tp->snd_cwnd,
+                  tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh
                   );
 }
 
@@ -2093,7 +2094,7 @@ struct proto tcpv6_prot = {
 #endif
 };
 
-static struct inet6_protocol tcpv6_protocol = {
+static const struct inet6_protocol tcpv6_protocol = {
        .handler        =       tcp_v6_rcv,
        .err_handler    =       tcp_v6_err,
        .gso_send_check =       tcp_v6_gso_send_check,
index 633ad789effc12d0000c9ec3bb2c76192bfcee6e..51e2832d13a661ee862b0ec0cd2e200bc2f5c7dd 100644 (file)
@@ -133,13 +133,13 @@ static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        break;
 }
 
-static struct inet6_protocol tunnel6_protocol = {
+static const struct inet6_protocol tunnel6_protocol = {
        .handler        = tunnel6_rcv,
        .err_handler    = tunnel6_err,
        .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
-static struct inet6_protocol tunnel46_protocol = {
+static const struct inet6_protocol tunnel46_protocol = {
        .handler        = tunnel46_rcv,
        .err_handler    = tunnel6_err,
        .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
index 164040613c2e996760ba756e5db89dd0e4f912a5..b265b7047d3e3b9795c348c92306c3b2b2970255 100644 (file)
@@ -1172,7 +1172,7 @@ out:
        return segs;
 }
 
-static struct inet6_protocol udpv6_protocol = {
+static const struct inet6_protocol udpv6_protocol = {
        .handler        =       udpv6_rcv,
        .err_handler    =       udpv6_err,
        .gso_send_check =       udp6_ufo_send_check,
index 4818c48688f210b31932329204b9c47159c5e44c..d737a27ee010e13e397605154654b3a68dd304c9 100644 (file)
@@ -25,7 +25,7 @@ static void udplitev6_err(struct sk_buff *skb,
        __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table);
 }
 
-static struct inet6_protocol udplitev6_protocol = {
+static const struct inet6_protocol udplitev6_protocol = {
        .handler        =       udplitev6_rcv,
        .err_handler    =       udplitev6_err,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
index 49c15b48408e5617a5405ba396f1f9b9e427dd5d..d985d163dcfc12590948cefcb5af50af3d08754e 100644 (file)
@@ -34,7 +34,7 @@
 
 static char iucv_userid[80];
 
-static struct proto_ops iucv_sock_ops;
+static const struct proto_ops iucv_sock_ops;
 
 static struct proto iucv_proto = {
        .name           = "AF_IUCV",
@@ -59,8 +59,8 @@ do {                                                                  \
        DEFINE_WAIT(__wait);                                            \
        long __timeo = timeo;                                           \
        ret = 0;                                                        \
+       prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE);     \
        while (!(condition)) {                                          \
-               prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \
                if (!__timeo) {                                         \
                        ret = -EAGAIN;                                  \
                        break;                                          \
@@ -361,10 +361,9 @@ static void iucv_sock_cleanup_listen(struct sock *parent)
        }
 
        parent->sk_state = IUCV_CLOSED;
-       sock_set_flag(parent, SOCK_ZAPPED);
 }
 
-/* Kill socket */
+/* Kill socket (only if zapped and orphaned) */
 static void iucv_sock_kill(struct sock *sk)
 {
        if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
@@ -426,17 +425,18 @@ static void iucv_sock_close(struct sock *sk)
 
                skb_queue_purge(&iucv->send_skb_q);
                skb_queue_purge(&iucv->backlog_skb_q);
-
-               sock_set_flag(sk, SOCK_ZAPPED);
                break;
 
        default:
                sock_set_flag(sk, SOCK_ZAPPED);
+               /* nothing to do here */
                break;
        }
 
+       /* mark socket for deletion by iucv_sock_kill() */
+       sock_set_flag(sk, SOCK_ZAPPED);
+
        release_sock(sk);
-       iucv_sock_kill(sk);
 }
 
 static void iucv_sock_init(struct sock *sk, struct sock *parent)
@@ -569,6 +569,7 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
 
                if (sk->sk_state == IUCV_CONNECTED ||
                    sk->sk_state == IUCV_SEVERED ||
+                   sk->sk_state == IUCV_DISCONN ||     /* due to PM restore */
                    !newsock) {
                        iucv_accept_unlink(sk);
                        if (newsock)
@@ -1035,6 +1036,10 @@ out:
        return err;
 }
 
+/* iucv_fragment_skb() - Fragment a single IUCV message into multiple skb's
+ *
+ * Locking: must be called with message_q.lock held
+ */
 static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
 {
        int dataleft, size, copied = 0;
@@ -1069,6 +1074,10 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
        return 0;
 }
 
+/* iucv_process_message() - Receive a single outstanding IUCV message
+ *
+ * Locking: must be called with message_q.lock held
+ */
 static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
                                 struct iucv_path *path,
                                 struct iucv_message *msg)
@@ -1119,6 +1128,10 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
                skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
 }
 
+/* iucv_process_message_q() - Process outstanding IUCV messages
+ *
+ * Locking: must be called with message_q.lock held
+ */
 static void iucv_process_message_q(struct sock *sk)
 {
        struct iucv_sock *iucv = iucv_sk(sk);
@@ -1209,6 +1222,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                kfree_skb(skb);
 
                /* Queue backlog skbs */
+               spin_lock_bh(&iucv->message_q.lock);
                rskb = skb_dequeue(&iucv->backlog_skb_q);
                while (rskb) {
                        if (sock_queue_rcv_skb(sk, rskb)) {
@@ -1220,11 +1234,10 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                        }
                }
                if (skb_queue_empty(&iucv->backlog_skb_q)) {
-                       spin_lock_bh(&iucv->message_q.lock);
                        if (!list_empty(&iucv->message_q.list))
                                iucv_process_message_q(sk);
-                       spin_unlock_bh(&iucv->message_q.lock);
                }
+               spin_unlock_bh(&iucv->message_q.lock);
        }
 
 done:
@@ -1682,7 +1695,7 @@ static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16])
        bh_unlock_sock(sk);
 }
 
-static struct proto_ops iucv_sock_ops = {
+static const struct proto_ops iucv_sock_ops = {
        .family         = PF_IUCV,
        .owner          = THIS_MODULE,
        .release        = iucv_sock_release,
index c833481d32e383439b98504e84a68250d4f9c98e..3973d0e61e56fefef8d0d775b728288061ad295c 100644 (file)
@@ -79,6 +79,14 @@ static int iucv_bus_match(struct device *dev, struct device_driver *drv)
        return 0;
 }
 
+enum iucv_pm_states {
+       IUCV_PM_INITIAL = 0,
+       IUCV_PM_FREEZING = 1,
+       IUCV_PM_THAWING = 2,
+       IUCV_PM_RESTORING = 3,
+};
+static enum iucv_pm_states iucv_pm_state;
+
 static int iucv_pm_prepare(struct device *);
 static void iucv_pm_complete(struct device *);
 static int iucv_pm_freeze(struct device *);
@@ -354,7 +362,7 @@ static int iucv_query_maxconn(void)
                "       srl     %0,28\n"
                : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
        if (ccode == 0)
-               iucv_max_pathid = reg0;
+               iucv_max_pathid = reg1;
        kfree(param);
        return ccode ? -EPERM : 0;
 }
@@ -856,7 +864,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -905,7 +913,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
 
        spin_lock_bh(&iucv_table_lock);
        iucv_cleanup_queue();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -965,7 +973,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -997,7 +1005,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1026,7 +1034,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
        int rc;
 
        preempt_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1060,7 +1068,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1152,7 +1160,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
        if (msg->flags & IUCV_IPRMDATA)
                return iucv_message_receive_iprmdata(path, msg, flags,
                                                     buffer, size, residual);
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1225,7 +1233,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1264,7 +1272,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1314,7 +1322,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
        union iucv_param *parm;
        int rc;
 
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1401,7 +1409,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
        int rc;
 
        local_bh_disable();
-       if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+       if (cpus_empty(iucv_buffer_cpumask)) {
                rc = -EIO;
                goto out;
        }
@@ -1875,6 +1883,7 @@ static int iucv_pm_freeze(struct device *dev)
 #ifdef CONFIG_PM_DEBUG
        printk(KERN_WARNING "iucv_pm_freeze\n");
 #endif
+       iucv_pm_state = IUCV_PM_FREEZING;
        for_each_cpu_mask_nr(cpu, iucv_irq_cpumask)
                smp_call_function_single(cpu, iucv_block_cpu_almost, NULL, 1);
        if (dev->driver && dev->driver->pm && dev->driver->pm->freeze)
@@ -1899,6 +1908,7 @@ static int iucv_pm_thaw(struct device *dev)
 #ifdef CONFIG_PM_DEBUG
        printk(KERN_WARNING "iucv_pm_thaw\n");
 #endif
+       iucv_pm_state = IUCV_PM_THAWING;
        if (!iucv_path_table) {
                rc = iucv_enable();
                if (rc)
@@ -1933,6 +1943,10 @@ static int iucv_pm_restore(struct device *dev)
 #ifdef CONFIG_PM_DEBUG
        printk(KERN_WARNING "iucv_pm_restore %p\n", iucv_path_table);
 #endif
+       if ((iucv_pm_state != IUCV_PM_RESTORING) && iucv_path_table)
+               pr_warning("Suspending Linux did not completely close all IUCV "
+                       "connections\n");
+       iucv_pm_state = IUCV_PM_RESTORING;
        if (cpus_empty(iucv_irq_cpumask)) {
                rc = iucv_query_maxconn();
                rc = iucv_enable();
index d0ff382c40ca96cfe66752379039218714c966a1..c5aab6a368ce250badd33ab0d30e858292f91521 100644 (file)
@@ -177,9 +177,11 @@ static void netlink_sock_destruct(struct sock *sk)
  * this, _but_ remember, it adds useless work on UP machines.
  */
 
-static void netlink_table_grab(void)
+void netlink_table_grab(void)
        __acquires(nl_table_lock)
 {
+       might_sleep();
+
        write_lock_irq(&nl_table_lock);
 
        if (atomic_read(&nl_table_users)) {
@@ -200,7 +202,7 @@ static void netlink_table_grab(void)
        }
 }
 
-static void netlink_table_ungrab(void)
+void netlink_table_ungrab(void)
        __releases(nl_table_lock)
 {
        write_unlock_irq(&nl_table_lock);
@@ -1549,37 +1551,21 @@ static void netlink_free_old_listeners(struct rcu_head *rcu_head)
        kfree(lrh->ptr);
 }
 
-/**
- * netlink_change_ngroups - change number of multicast groups
- *
- * This changes the number of multicast groups that are available
- * on a certain netlink family. Note that it is not possible to
- * change the number of groups to below 32. Also note that it does
- * not implicitly call netlink_clear_multicast_users() when the
- * number of groups is reduced.
- *
- * @sk: The kernel netlink socket, as returned by netlink_kernel_create().
- * @groups: The new number of groups.
- */
-int netlink_change_ngroups(struct sock *sk, unsigned int groups)
+int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
 {
        unsigned long *listeners, *old = NULL;
        struct listeners_rcu_head *old_rcu_head;
        struct netlink_table *tbl = &nl_table[sk->sk_protocol];
-       int err = 0;
 
        if (groups < 32)
                groups = 32;
 
-       netlink_table_grab();
        if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
                listeners = kzalloc(NLGRPSZ(groups) +
                                    sizeof(struct listeners_rcu_head),
                                    GFP_ATOMIC);
-               if (!listeners) {
-                       err = -ENOMEM;
-                       goto out_ungrab;
-               }
+               if (!listeners)
+                       return -ENOMEM;
                old = tbl->listeners;
                memcpy(listeners, old, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, listeners);
@@ -1597,8 +1583,29 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
        }
        tbl->groups = groups;
 
- out_ungrab:
+       return 0;
+}
+
+/**
+ * netlink_change_ngroups - change number of multicast groups
+ *
+ * This changes the number of multicast groups that are available
+ * on a certain netlink family. Note that it is not possible to
+ * change the number of groups to below 32. Also note that it does
+ * not implicitly call netlink_clear_multicast_users() when the
+ * number of groups is reduced.
+ *
+ * @sk: The kernel netlink socket, as returned by netlink_kernel_create().
+ * @groups: The new number of groups.
+ */
+int netlink_change_ngroups(struct sock *sk, unsigned int groups)
+{
+       int err;
+
+       netlink_table_grab();
+       err = __netlink_change_ngroups(sk, groups);
        netlink_table_ungrab();
+
        return err;
 }
 
index 66f6ba0bab11932c9b1302a555f9bcefb52065dd..566941e03363fbdd7591ded5ed16b41f0a903c7c 100644 (file)
@@ -176,9 +176,10 @@ int genl_register_mc_group(struct genl_family *family,
        if (family->netnsok) {
                struct net *net;
 
+               netlink_table_grab();
                rcu_read_lock();
                for_each_net_rcu(net) {
-                       err = netlink_change_ngroups(net->genl_sock,
+                       err = __netlink_change_ngroups(net->genl_sock,
                                        mc_groups_longs * BITS_PER_LONG);
                        if (err) {
                                /*
@@ -188,10 +189,12 @@ int genl_register_mc_group(struct genl_family *family,
                                 * increased on some sockets which is ok.
                                 */
                                rcu_read_unlock();
+                               netlink_table_ungrab();
                                goto out;
                        }
                }
                rcu_read_unlock();
+               netlink_table_ungrab();
        } else {
                err = netlink_change_ngroups(init_net.genl_sock,
                                             mc_groups_longs * BITS_PER_LONG);
index 2f65dcaed2fb072056ee2b3a11a89fa7033dc903..5f42f30dd1682bdc2427e7b387390fe231ab305e 100644 (file)
@@ -209,7 +209,14 @@ static int phonet_device_autoconf(struct net_device *dev)
                                                SIOCPNGAUTOCONF);
        if (ret < 0)
                return ret;
-       return phonet_address_add(dev, req.ifr_phonet_autoconf.device);
+
+       ASSERT_RTNL();
+       ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device);
+       if (ret)
+               return ret;
+       phonet_address_notify(RTM_NEWADDR, dev,
+                               req.ifr_phonet_autoconf.device);
+       return 0;
 }
 
 /* notify Phonet of device events */
index 108ed2e671c5599a413d028feb1591962c978004..6b58aeff4c7ab72b4072799b63e2f0dd8d466a5c 100644 (file)
@@ -359,7 +359,7 @@ static struct proto rds_proto = {
        .obj_size = sizeof(struct rds_sock),
 };
 
-static struct proto_ops rds_proto_ops = {
+static const struct proto_ops rds_proto_ops = {
        .family =       AF_RDS,
        .owner =        THIS_MODULE,
        .release =      rds_release,
index e5f478ca3d61574e01bc74bad58cfdc910a33b4a..1e166c9685aac9c479eb7720a28f7dff4ecaa6f2 100644 (file)
@@ -63,7 +63,7 @@ int sysctl_rose_window_size             = ROSE_DEFAULT_WINDOW_SIZE;
 static HLIST_HEAD(rose_list);
 static DEFINE_SPINLOCK(rose_list_lock);
 
-static struct proto_ops rose_proto_ops;
+static const struct proto_ops rose_proto_ops;
 
 ax25_address rose_callsign;
 
@@ -1515,7 +1515,7 @@ static struct net_proto_family rose_family_ops = {
        .owner          =       THIS_MODULE,
 };
 
-static struct proto_ops rose_proto_ops = {
+static const struct proto_ops rose_proto_ops = {
        .family         =       PF_ROSE,
        .owner          =       THIS_MODULE,
        .release        =       rose_release,
index c9f1f0a3a2ff4a520e3c7a002115e7e646c2cee4..b4a2209770311a4fdce0757c9857bbdd6fdf2f39 100644 (file)
@@ -40,7 +40,7 @@ static const s8 rxrpc_ack_priority[] = {
 /*
  * propose an ACK be sent
  */
-void __rxrpc_propose_ACK(struct rxrpc_call *call, uint8_t ack_reason,
+void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                         __be32 serial, bool immediate)
 {
        unsigned long expiry;
@@ -120,7 +120,7 @@ cancel_timer:
 /*
  * propose an ACK be sent, locking the call structure
  */
-void rxrpc_propose_ACK(struct rxrpc_call *call, uint8_t ack_reason,
+void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                       __be32 serial, bool immediate)
 {
        s8 prior = rxrpc_ack_priority[ack_reason];
@@ -520,7 +520,7 @@ static void rxrpc_zap_tx_window(struct rxrpc_call *call)
        struct rxrpc_skb_priv *sp;
        struct sk_buff *skb;
        unsigned long _skb, *acks_window;
-       uint8_t winsz = call->acks_winsz;
+       u8 winsz = call->acks_winsz;
        int tail;
 
        acks_window = call->acks_window;
index 3e7318c1343cb886d3aacf4e70df5b50200349ab..7043b294bb67d6266621949aa20cd5e6fa7180c4 100644 (file)
@@ -229,7 +229,7 @@ struct rxrpc_conn_bundle {
        int                     debug_id;       /* debug ID for printks */
        unsigned short          num_conns;      /* number of connections in this bundle */
        __be16                  service_id;     /* service ID */
-       uint8_t                 security_ix;    /* security type */
+       u8                      security_ix;    /* security type */
 };
 
 /*
@@ -370,10 +370,10 @@ struct rxrpc_call {
        u8                      channel;        /* connection channel occupied by this call */
 
        /* transmission-phase ACK management */
-       uint8_t                 acks_head;      /* offset into window of first entry */
-       uint8_t                 acks_tail;      /* offset into window of last entry */
-       uint8_t                 acks_winsz;     /* size of un-ACK'd window */
-       uint8_t                 acks_unacked;   /* lowest unacked packet in last ACK received */
+       u8                      acks_head;      /* offset into window of first entry */
+       u8                      acks_tail;      /* offset into window of last entry */
+       u8                      acks_winsz;     /* size of un-ACK'd window */
+       u8                      acks_unacked;   /* lowest unacked packet in last ACK received */
        int                     acks_latest;    /* serial number of latest ACK received */
        rxrpc_seq_t             acks_hard;      /* highest definitively ACK'd msg seq */
        unsigned long           *acks_window;   /* sent packet window
@@ -388,7 +388,7 @@ struct rxrpc_call {
        rxrpc_seq_t             rx_first_oos;   /* first packet in rx_oos_queue (or 0) */
        rxrpc_seq_t             ackr_win_top;   /* top of ACK window (rx_data_eaten is bottom) */
        rxrpc_seq_net_t         ackr_prev_seq;  /* previous sequence number received */
-       uint8_t                 ackr_reason;    /* reason to ACK */
+       u8                      ackr_reason;    /* reason to ACK */
        __be32                  ackr_serial;    /* serial of packet being ACK'd */
        atomic_t                ackr_not_idle;  /* number of packets in Rx queue */
 
@@ -401,22 +401,6 @@ struct rxrpc_call {
        __be32                  call_id;        /* call ID on connection  */
 };
 
-/*
- * RxRPC key for Kerberos (type-2 security)
- */
-struct rxkad_key {
-       u16     security_index;         /* RxRPC header security index */
-       u16     ticket_len;             /* length of ticket[] */
-       u32     expiry;                 /* time at which expires */
-       u32     kvno;                   /* key version number */
-       u8      session_key[8];         /* DES session key */
-       u8      ticket[0];              /* the encrypted ticket */
-};
-
-struct rxrpc_key_payload {
-       struct rxkad_key k;
-};
-
 /*
  * locally abort an RxRPC call
  */
@@ -450,8 +434,8 @@ extern int rxrpc_reject_call(struct rxrpc_sock *);
 /*
  * ar-ack.c
  */
-extern void __rxrpc_propose_ACK(struct rxrpc_call *, uint8_t, __be32, bool);
-extern void rxrpc_propose_ACK(struct rxrpc_call *, uint8_t, __be32, bool);
+extern void __rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool);
+extern void rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool);
 extern void rxrpc_process_call(struct work_struct *);
 
 /*
index ad8c7a782da1f0daabcd7ff1f9076e1785ae0f23..74697b2004962059857c6b42e84a5490befce23d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/skbuff.h>
 #include <linux/key-type.h>
 #include <linux/crypto.h>
+#include <linux/ctype.h>
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
 #include <keys/rxrpc-type.h>
@@ -28,6 +29,7 @@ static int rxrpc_instantiate_s(struct key *, const void *, size_t);
 static void rxrpc_destroy(struct key *);
 static void rxrpc_destroy_s(struct key *);
 static void rxrpc_describe(const struct key *, struct seq_file *);
+static long rxrpc_read(const struct key *, char __user *, size_t);
 
 /*
  * rxrpc defined keys take an arbitrary string as the description and an
@@ -39,6 +41,7 @@ struct key_type key_type_rxrpc = {
        .match          = user_match,
        .destroy        = rxrpc_destroy,
        .describe       = rxrpc_describe,
+       .read           = rxrpc_read,
 };
 EXPORT_SYMBOL(key_type_rxrpc);
 
@@ -54,6 +57,595 @@ struct key_type key_type_rxrpc_s = {
        .describe       = rxrpc_describe,
 };
 
+/*
+ * parse an RxKAD type XDR format token
+ * - the caller guarantees we have at least 4 words
+ */
+static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
+                                      unsigned toklen)
+{
+       struct rxrpc_key_token *token, **pptoken;
+       size_t plen;
+       u32 tktlen;
+       int ret;
+
+       _enter(",{%x,%x,%x,%x},%u",
+              ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
+              toklen);
+
+       if (toklen <= 8 * 4)
+               return -EKEYREJECTED;
+       tktlen = ntohl(xdr[7]);
+       _debug("tktlen: %x", tktlen);
+       if (tktlen > AFSTOKEN_RK_TIX_MAX)
+               return -EKEYREJECTED;
+       if (8 * 4 + tktlen != toklen)
+               return -EKEYREJECTED;
+
+       plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
+       ret = key_payload_reserve(key, key->datalen + plen);
+       if (ret < 0)
+               return ret;
+
+       plen -= sizeof(*token);
+       token = kmalloc(sizeof(*token), GFP_KERNEL);
+       if (!token)
+               return -ENOMEM;
+
+       token->kad = kmalloc(plen, GFP_KERNEL);
+       if (!token->kad) {
+               kfree(token);
+               return -ENOMEM;
+       }
+
+       token->security_index   = RXRPC_SECURITY_RXKAD;
+       token->kad->ticket_len  = tktlen;
+       token->kad->vice_id     = ntohl(xdr[0]);
+       token->kad->kvno        = ntohl(xdr[1]);
+       token->kad->start       = ntohl(xdr[4]);
+       token->kad->expiry      = ntohl(xdr[5]);
+       token->kad->primary_flag = ntohl(xdr[6]);
+       memcpy(&token->kad->session_key, &xdr[2], 8);
+       memcpy(&token->kad->ticket, &xdr[8], tktlen);
+
+       _debug("SCIX: %u", token->security_index);
+       _debug("TLEN: %u", token->kad->ticket_len);
+       _debug("EXPY: %x", token->kad->expiry);
+       _debug("KVNO: %u", token->kad->kvno);
+       _debug("PRIM: %u", token->kad->primary_flag);
+       _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
+              token->kad->session_key[0], token->kad->session_key[1],
+              token->kad->session_key[2], token->kad->session_key[3],
+              token->kad->session_key[4], token->kad->session_key[5],
+              token->kad->session_key[6], token->kad->session_key[7]);
+       if (token->kad->ticket_len >= 8)
+               _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
+                      token->kad->ticket[0], token->kad->ticket[1],
+                      token->kad->ticket[2], token->kad->ticket[3],
+                      token->kad->ticket[4], token->kad->ticket[5],
+                      token->kad->ticket[6], token->kad->ticket[7]);
+
+       /* count the number of tokens attached */
+       key->type_data.x[0]++;
+
+       /* attach the data */
+       for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
+            *pptoken;
+            pptoken = &(*pptoken)->next)
+               continue;
+       *pptoken = token;
+       if (token->kad->expiry < key->expiry)
+               key->expiry = token->kad->expiry;
+
+       _leave(" = 0");
+       return 0;
+}
+
+static void rxrpc_free_krb5_principal(struct krb5_principal *princ)
+{
+       int loop;
+
+       if (princ->name_parts) {
+               for (loop = princ->n_name_parts - 1; loop >= 0; loop--)
+                       kfree(princ->name_parts[loop]);
+               kfree(princ->name_parts);
+       }
+       kfree(princ->realm);
+}
+
+static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td)
+{
+       kfree(td->data);
+}
+
+/*
+ * free up an RxK5 token
+ */
+static void rxrpc_rxk5_free(struct rxk5_key *rxk5)
+{
+       int loop;
+
+       rxrpc_free_krb5_principal(&rxk5->client);
+       rxrpc_free_krb5_principal(&rxk5->server);
+       rxrpc_free_krb5_tagged(&rxk5->session);
+
+       if (rxk5->addresses) {
+               for (loop = rxk5->n_addresses - 1; loop >= 0; loop--)
+                       rxrpc_free_krb5_tagged(&rxk5->addresses[loop]);
+               kfree(rxk5->addresses);
+       }
+       if (rxk5->authdata) {
+               for (loop = rxk5->n_authdata - 1; loop >= 0; loop--)
+                       rxrpc_free_krb5_tagged(&rxk5->authdata[loop]);
+               kfree(rxk5->authdata);
+       }
+
+       kfree(rxk5->ticket);
+       kfree(rxk5->ticket2);
+       kfree(rxk5);
+}
+
+/*
+ * extract a krb5 principal
+ */
+static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
+                                      const __be32 **_xdr,
+                                      unsigned *_toklen)
+{
+       const __be32 *xdr = *_xdr;
+       unsigned toklen = *_toklen, n_parts, loop, tmp;
+
+       /* there must be at least one name, and at least #names+1 length
+        * words */
+       if (toklen <= 12)
+               return -EINVAL;
+
+       _enter(",{%x,%x,%x},%u",
+              ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), toklen);
+
+       n_parts = ntohl(*xdr++);
+       toklen -= 4;
+       if (n_parts <= 0 || n_parts > AFSTOKEN_K5_COMPONENTS_MAX)
+               return -EINVAL;
+       princ->n_name_parts = n_parts;
+
+       if (toklen <= (n_parts + 1) * 4)
+               return -EINVAL;
+
+       princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL);
+       if (!princ->name_parts)
+               return -ENOMEM;
+
+       for (loop = 0; loop < n_parts; loop++) {
+               if (toklen < 4)
+                       return -EINVAL;
+               tmp = ntohl(*xdr++);
+               toklen -= 4;
+               if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
+                       return -EINVAL;
+               if (tmp > toklen)
+                       return -EINVAL;
+               princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
+               if (!princ->name_parts[loop])
+                       return -ENOMEM;
+               memcpy(princ->name_parts[loop], xdr, tmp);
+               princ->name_parts[loop][tmp] = 0;
+               tmp = (tmp + 3) & ~3;
+               toklen -= tmp;
+               xdr += tmp >> 2;
+       }
+
+       if (toklen < 4)
+               return -EINVAL;
+       tmp = ntohl(*xdr++);
+       toklen -= 4;
+       if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
+               return -EINVAL;
+       if (tmp > toklen)
+               return -EINVAL;
+       princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
+       if (!princ->realm)
+               return -ENOMEM;
+       memcpy(princ->realm, xdr, tmp);
+       princ->realm[tmp] = 0;
+       tmp = (tmp + 3) & ~3;
+       toklen -= tmp;
+       xdr += tmp >> 2;
+
+       _debug("%s/...@%s", princ->name_parts[0], princ->realm);
+
+       *_xdr = xdr;
+       *_toklen = toklen;
+       _leave(" = 0 [toklen=%u]", toklen);
+       return 0;
+}
+
+/*
+ * extract a piece of krb5 tagged data
+ */
+static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
+                                        size_t max_data_size,
+                                        const __be32 **_xdr,
+                                        unsigned *_toklen)
+{
+       const __be32 *xdr = *_xdr;
+       unsigned toklen = *_toklen, len;
+
+       /* there must be at least one tag and one length word */
+       if (toklen <= 8)
+               return -EINVAL;
+
+       _enter(",%zu,{%x,%x},%u",
+              max_data_size, ntohl(xdr[0]), ntohl(xdr[1]), toklen);
+
+       td->tag = ntohl(*xdr++);
+       len = ntohl(*xdr++);
+       toklen -= 8;
+       if (len > max_data_size)
+               return -EINVAL;
+       td->data_len = len;
+
+       if (len > 0) {
+               td->data = kmalloc(len, GFP_KERNEL);
+               if (!td->data)
+                       return -ENOMEM;
+               memcpy(td->data, xdr, len);
+               len = (len + 3) & ~3;
+               toklen -= len;
+               xdr += len >> 2;
+       }
+
+       _debug("tag %x len %x", td->tag, td->data_len);
+
+       *_xdr = xdr;
+       *_toklen = toklen;
+       _leave(" = 0 [toklen=%u]", toklen);
+       return 0;
+}
+
+/*
+ * extract an array of tagged data
+ */
+static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
+                                         u8 *_n_elem,
+                                         u8 max_n_elem,
+                                         size_t max_elem_size,
+                                         const __be32 **_xdr,
+                                         unsigned *_toklen)
+{
+       struct krb5_tagged_data *td;
+       const __be32 *xdr = *_xdr;
+       unsigned toklen = *_toklen, n_elem, loop;
+       int ret;
+
+       /* there must be at least one count */
+       if (toklen < 4)
+               return -EINVAL;
+
+       _enter(",,%u,%zu,{%x},%u",
+              max_n_elem, max_elem_size, ntohl(xdr[0]), toklen);
+
+       n_elem = ntohl(*xdr++);
+       toklen -= 4;
+       if (n_elem < 0 || n_elem > max_n_elem)
+               return -EINVAL;
+       *_n_elem = n_elem;
+       if (n_elem > 0) {
+               if (toklen <= (n_elem + 1) * 4)
+                       return -EINVAL;
+
+               _debug("n_elem %d", n_elem);
+
+               td = kcalloc(sizeof(struct krb5_tagged_data), n_elem,
+                            GFP_KERNEL);
+               if (!td)
+                       return -ENOMEM;
+               *_td = td;
+
+               for (loop = 0; loop < n_elem; loop++) {
+                       ret = rxrpc_krb5_decode_tagged_data(&td[loop],
+                                                           max_elem_size,
+                                                           &xdr, &toklen);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       *_xdr = xdr;
+       *_toklen = toklen;
+       _leave(" = 0 [toklen=%u]", toklen);
+       return 0;
+}
+
+/*
+ * extract a krb5 ticket
+ */
+static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
+                                   const __be32 **_xdr, unsigned *_toklen)
+{
+       const __be32 *xdr = *_xdr;
+       unsigned toklen = *_toklen, len;
+
+       /* there must be at least one length word */
+       if (toklen <= 4)
+               return -EINVAL;
+
+       _enter(",{%x},%u", ntohl(xdr[0]), toklen);
+
+       len = ntohl(*xdr++);
+       toklen -= 4;
+       if (len > AFSTOKEN_K5_TIX_MAX)
+               return -EINVAL;
+       *_tktlen = len;
+
+       _debug("ticket len %u", len);
+
+       if (len > 0) {
+               *_ticket = kmalloc(len, GFP_KERNEL);
+               if (!*_ticket)
+                       return -ENOMEM;
+               memcpy(*_ticket, xdr, len);
+               len = (len + 3) & ~3;
+               toklen -= len;
+               xdr += len >> 2;
+       }
+
+       *_xdr = xdr;
+       *_toklen = toklen;
+       _leave(" = 0 [toklen=%u]", toklen);
+       return 0;
+}
+
+/*
+ * parse an RxK5 type XDR format token
+ * - the caller guarantees we have at least 4 words
+ */
+static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
+                                     unsigned toklen)
+{
+       struct rxrpc_key_token *token, **pptoken;
+       struct rxk5_key *rxk5;
+       const __be32 *end_xdr = xdr + (toklen >> 2);
+       int ret;
+
+       _enter(",{%x,%x,%x,%x},%u",
+              ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
+              toklen);
+
+       /* reserve some payload space for this subkey - the length of the token
+        * is a reasonable approximation */
+       ret = key_payload_reserve(key, key->datalen + toklen);
+       if (ret < 0)
+               return ret;
+
+       token = kzalloc(sizeof(*token), GFP_KERNEL);
+       if (!token)
+               return -ENOMEM;
+
+       rxk5 = kzalloc(sizeof(*rxk5), GFP_KERNEL);
+       if (!rxk5) {
+               kfree(token);
+               return -ENOMEM;
+       }
+
+       token->security_index = RXRPC_SECURITY_RXK5;
+       token->k5 = rxk5;
+
+       /* extract the principals */
+       ret = rxrpc_krb5_decode_principal(&rxk5->client, &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+       ret = rxrpc_krb5_decode_principal(&rxk5->server, &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+
+       /* extract the session key and the encoding type (the tag field ->
+        * ENCTYPE_xxx) */
+       ret = rxrpc_krb5_decode_tagged_data(&rxk5->session, AFSTOKEN_DATA_MAX,
+                                           &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+
+       if (toklen < 4 * 8 + 2 * 4)
+               goto inval;
+       rxk5->authtime  = be64_to_cpup((const __be64 *) xdr);
+       xdr += 2;
+       rxk5->starttime = be64_to_cpup((const __be64 *) xdr);
+       xdr += 2;
+       rxk5->endtime   = be64_to_cpup((const __be64 *) xdr);
+       xdr += 2;
+       rxk5->renew_till = be64_to_cpup((const __be64 *) xdr);
+       xdr += 2;
+       rxk5->is_skey = ntohl(*xdr++);
+       rxk5->flags = ntohl(*xdr++);
+       toklen -= 4 * 8 + 2 * 4;
+
+       _debug("times: a=%llx s=%llx e=%llx rt=%llx",
+              rxk5->authtime, rxk5->starttime, rxk5->endtime,
+              rxk5->renew_till);
+       _debug("is_skey=%x flags=%x", rxk5->is_skey, rxk5->flags);
+
+       /* extract the permitted client addresses */
+       ret = rxrpc_krb5_decode_tagged_array(&rxk5->addresses,
+                                            &rxk5->n_addresses,
+                                            AFSTOKEN_K5_ADDRESSES_MAX,
+                                            AFSTOKEN_DATA_MAX,
+                                            &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+
+       ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
+
+       /* extract the tickets */
+       ret = rxrpc_krb5_decode_ticket(&rxk5->ticket, &rxk5->ticket_len,
+                                      &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+       ret = rxrpc_krb5_decode_ticket(&rxk5->ticket2, &rxk5->ticket2_len,
+                                      &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+
+       ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
+
+       /* extract the typed auth data */
+       ret = rxrpc_krb5_decode_tagged_array(&rxk5->authdata,
+                                            &rxk5->n_authdata,
+                                            AFSTOKEN_K5_AUTHDATA_MAX,
+                                            AFSTOKEN_BDATALN_MAX,
+                                            &xdr, &toklen);
+       if (ret < 0)
+               goto error;
+
+       ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
+
+       if (toklen != 0)
+               goto inval;
+
+       /* attach the payload to the key */
+       for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
+            *pptoken;
+            pptoken = &(*pptoken)->next)
+               continue;
+       *pptoken = token;
+       if (token->kad->expiry < key->expiry)
+               key->expiry = token->kad->expiry;
+
+       _leave(" = 0");
+       return 0;
+
+inval:
+       ret = -EINVAL;
+error:
+       rxrpc_rxk5_free(rxk5);
+       kfree(token);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * attempt to parse the data as the XDR format
+ * - the caller guarantees we have more than 7 words
+ */
+static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen)
+{
+       const __be32 *xdr = data, *token;
+       const char *cp;
+       unsigned len, tmp, loop, ntoken, toklen, sec_ix;
+       int ret;
+
+       _enter(",{%x,%x,%x,%x},%zu",
+              ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
+              datalen);
+
+       if (datalen > AFSTOKEN_LENGTH_MAX)
+               goto not_xdr;
+
+       /* XDR is an array of __be32's */
+       if (datalen & 3)
+               goto not_xdr;
+
+       /* the flags should be 0 (the setpag bit must be handled by
+        * userspace) */
+       if (ntohl(*xdr++) != 0)
+               goto not_xdr;
+       datalen -= 4;
+
+       /* check the cell name */
+       len = ntohl(*xdr++);
+       if (len < 1 || len > AFSTOKEN_CELL_MAX)
+               goto not_xdr;
+       datalen -= 4;
+       tmp = (len + 3) & ~3;
+       if (tmp > datalen)
+               goto not_xdr;
+
+       cp = (const char *) xdr;
+       for (loop = 0; loop < len; loop++)
+               if (!isprint(cp[loop]))
+                       goto not_xdr;
+       if (len < tmp)
+               for (; loop < tmp; loop++)
+                       if (cp[loop])
+                               goto not_xdr;
+       _debug("cellname: [%u/%u] '%*.*s'",
+              len, tmp, len, len, (const char *) xdr);
+       datalen -= tmp;
+       xdr += tmp >> 2;
+
+       /* get the token count */
+       if (datalen < 12)
+               goto not_xdr;
+       ntoken = ntohl(*xdr++);
+       datalen -= 4;
+       _debug("ntoken: %x", ntoken);
+       if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
+               goto not_xdr;
+
+       /* check each token wrapper */
+       token = xdr;
+       loop = ntoken;
+       do {
+               if (datalen < 8)
+                       goto not_xdr;
+               toklen = ntohl(*xdr++);
+               sec_ix = ntohl(*xdr);
+               datalen -= 4;
+               _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
+               if (toklen < 20 || toklen > datalen)
+                       goto not_xdr;
+               datalen -= (toklen + 3) & ~3;
+               xdr += (toklen + 3) >> 2;
+
+       } while (--loop > 0);
+
+       _debug("remainder: %zu", datalen);
+       if (datalen != 0)
+               goto not_xdr;
+
+       /* okay: we're going to assume it's valid XDR format
+        * - we ignore the cellname, relying on the key to be correctly named
+        */
+       do {
+               xdr = token;
+               toklen = ntohl(*xdr++);
+               token = xdr + ((toklen + 3) >> 2);
+               sec_ix = ntohl(*xdr++);
+               toklen -= 4;
+
+               _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
+
+               switch (sec_ix) {
+               case RXRPC_SECURITY_RXKAD:
+                       ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
+                       if (ret != 0)
+                               goto error;
+                       break;
+
+               case RXRPC_SECURITY_RXK5:
+                       ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen);
+                       if (ret != 0)
+                               goto error;
+                       break;
+
+               default:
+                       ret = -EPROTONOSUPPORT;
+                       goto error;
+               }
+
+       } while (--ntoken > 0);
+
+       _leave(" = 0");
+       return 0;
+
+not_xdr:
+       _leave(" = -EPROTO");
+       return -EPROTO;
+error:
+       _leave(" = %d", ret);
+       return ret;
+}
+
 /*
  * instantiate an rxrpc defined key
  * data should be of the form:
@@ -70,8 +662,8 @@ struct key_type key_type_rxrpc_s = {
  */
 static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
 {
-       const struct rxkad_key *tsec;
-       struct rxrpc_key_payload *upayload;
+       const struct rxrpc_key_data_v1 *v1;
+       struct rxrpc_key_token *token, **pp;
        size_t plen;
        u32 kver;
        int ret;
@@ -82,6 +674,13 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
        if (!data && datalen == 0)
                return 0;
 
+       /* determine if the XDR payload format is being used */
+       if (datalen > 7 * 4) {
+               ret = rxrpc_instantiate_xdr(key, data, datalen);
+               if (ret != -EPROTO)
+                       return ret;
+       }
+
        /* get the key interface version number */
        ret = -EINVAL;
        if (datalen <= 4 || !data)
@@ -98,53 +697,67 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
 
        /* deal with a version 1 key */
        ret = -EINVAL;
-       if (datalen < sizeof(*tsec))
+       if (datalen < sizeof(*v1))
                goto error;
 
-       tsec = data;
-       if (datalen != sizeof(*tsec) + tsec->ticket_len)
+       v1 = data;
+       if (datalen != sizeof(*v1) + v1->ticket_length)
                goto error;
 
-       _debug("SCIX: %u", tsec->security_index);
-       _debug("TLEN: %u", tsec->ticket_len);
-       _debug("EXPY: %x", tsec->expiry);
-       _debug("KVNO: %u", tsec->kvno);
+       _debug("SCIX: %u", v1->security_index);
+       _debug("TLEN: %u", v1->ticket_length);
+       _debug("EXPY: %x", v1->expiry);
+       _debug("KVNO: %u", v1->kvno);
        _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
-              tsec->session_key[0], tsec->session_key[1],
-              tsec->session_key[2], tsec->session_key[3],
-              tsec->session_key[4], tsec->session_key[5],
-              tsec->session_key[6], tsec->session_key[7]);
-       if (tsec->ticket_len >= 8)
+              v1->session_key[0], v1->session_key[1],
+              v1->session_key[2], v1->session_key[3],
+              v1->session_key[4], v1->session_key[5],
+              v1->session_key[6], v1->session_key[7]);
+       if (v1->ticket_length >= 8)
                _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
-                      tsec->ticket[0], tsec->ticket[1],
-                      tsec->ticket[2], tsec->ticket[3],
-                      tsec->ticket[4], tsec->ticket[5],
-                      tsec->ticket[6], tsec->ticket[7]);
+                      v1->ticket[0], v1->ticket[1],
+                      v1->ticket[2], v1->ticket[3],
+                      v1->ticket[4], v1->ticket[5],
+                      v1->ticket[6], v1->ticket[7]);
 
        ret = -EPROTONOSUPPORT;
-       if (tsec->security_index != 2)
+       if (v1->security_index != RXRPC_SECURITY_RXKAD)
                goto error;
 
-       key->type_data.x[0] = tsec->security_index;
-
-       plen = sizeof(*upayload) + tsec->ticket_len;
-       ret = key_payload_reserve(key, plen);
+       plen = sizeof(*token->kad) + v1->ticket_length;
+       ret = key_payload_reserve(key, plen + sizeof(*token));
        if (ret < 0)
                goto error;
 
        ret = -ENOMEM;
-       upayload = kmalloc(plen, GFP_KERNEL);
-       if (!upayload)
+       token = kmalloc(sizeof(*token), GFP_KERNEL);
+       if (!token)
                goto error;
+       token->kad = kmalloc(plen, GFP_KERNEL);
+       if (!token->kad)
+               goto error_free;
+
+       token->security_index           = RXRPC_SECURITY_RXKAD;
+       token->kad->ticket_len          = v1->ticket_length;
+       token->kad->expiry              = v1->expiry;
+       token->kad->kvno                = v1->kvno;
+       memcpy(&token->kad->session_key, &v1->session_key, 8);
+       memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
 
        /* attach the data */
-       memcpy(&upayload->k, tsec, sizeof(*tsec));
-       memcpy(&upayload->k.ticket, (void *)tsec + sizeof(*tsec),
-              tsec->ticket_len);
-       key->payload.data = upayload;
-       key->expiry = tsec->expiry;
+       key->type_data.x[0]++;
+
+       pp = (struct rxrpc_key_token **)&key->payload.data;
+       while (*pp)
+               pp = &(*pp)->next;
+       *pp = token;
+       if (token->kad->expiry < key->expiry)
+               key->expiry = token->kad->expiry;
+       token = NULL;
        ret = 0;
 
+error_free:
+       kfree(token);
 error:
        return ret;
 }
@@ -184,7 +797,26 @@ static int rxrpc_instantiate_s(struct key *key, const void *data,
  */
 static void rxrpc_destroy(struct key *key)
 {
-       kfree(key->payload.data);
+       struct rxrpc_key_token *token;
+
+       while ((token = key->payload.data)) {
+               key->payload.data = token->next;
+               switch (token->security_index) {
+               case RXRPC_SECURITY_RXKAD:
+                       kfree(token->kad);
+                       break;
+               case RXRPC_SECURITY_RXK5:
+                       if (token->k5)
+                               rxrpc_rxk5_free(token->k5);
+                       break;
+               default:
+                       printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
+                              token->security_index);
+                       BUG();
+               }
+
+               kfree(token);
+       }
 }
 
 /*
@@ -293,7 +925,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
 
        struct {
                u32 kver;
-               struct rxkad_key tsec;
+               struct rxrpc_key_data_v1 v1;
        } data;
 
        _enter("");
@@ -308,13 +940,12 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
        _debug("key %d", key_serial(key));
 
        data.kver = 1;
-       data.tsec.security_index = 2;
-       data.tsec.ticket_len = 0;
-       data.tsec.expiry = expiry;
-       data.tsec.kvno = 0;
+       data.v1.security_index = RXRPC_SECURITY_RXKAD;
+       data.v1.ticket_length = 0;
+       data.v1.expiry = expiry;
+       data.v1.kvno = 0;
 
-       memcpy(&data.tsec.session_key, session_key,
-              sizeof(data.tsec.session_key));
+       memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
 
        ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
        if (ret < 0)
@@ -360,3 +991,210 @@ struct key *rxrpc_get_null_key(const char *keyname)
        return key;
 }
 EXPORT_SYMBOL(rxrpc_get_null_key);
+
+/*
+ * read the contents of an rxrpc key
+ * - this returns the result in XDR form
+ */
+static long rxrpc_read(const struct key *key,
+                      char __user *buffer, size_t buflen)
+{
+       const struct rxrpc_key_token *token;
+       const struct krb5_principal *princ;
+       size_t size;
+       __be32 __user *xdr, *oldxdr;
+       u32 cnlen, toksize, ntoks, tok, zero;
+       u16 toksizes[AFSTOKEN_MAX];
+       int loop;
+
+       _enter("");
+
+       /* we don't know what form we should return non-AFS keys in */
+       if (memcmp(key->description, "afs@", 4) != 0)
+               return -EOPNOTSUPP;
+       cnlen = strlen(key->description + 4);
+
+#define RND(X) (((X) + 3) & ~3)
+
+       /* AFS keys we return in XDR form, so we need to work out the size of
+        * the XDR */
+       size = 2 * 4;   /* flags, cellname len */
+       size += RND(cnlen);     /* cellname */
+       size += 1 * 4;  /* token count */
+
+       ntoks = 0;
+       for (token = key->payload.data; token; token = token->next) {
+               toksize = 4;    /* sec index */
+
+               switch (token->security_index) {
+               case RXRPC_SECURITY_RXKAD:
+                       toksize += 8 * 4;       /* viceid, kvno, key*2, begin,
+                                                * end, primary, tktlen */
+                       toksize += RND(token->kad->ticket_len);
+                       break;
+
+               case RXRPC_SECURITY_RXK5:
+                       princ = &token->k5->client;
+                       toksize += 4 + princ->n_name_parts * 4;
+                       for (loop = 0; loop < princ->n_name_parts; loop++)
+                               toksize += RND(strlen(princ->name_parts[loop]));
+                       toksize += 4 + RND(strlen(princ->realm));
+
+                       princ = &token->k5->server;
+                       toksize += 4 + princ->n_name_parts * 4;
+                       for (loop = 0; loop < princ->n_name_parts; loop++)
+                               toksize += RND(strlen(princ->name_parts[loop]));
+                       toksize += 4 + RND(strlen(princ->realm));
+
+                       toksize += 8 + RND(token->k5->session.data_len);
+
+                       toksize += 4 * 8 + 2 * 4;
+
+                       toksize += 4 + token->k5->n_addresses * 8;
+                       for (loop = 0; loop < token->k5->n_addresses; loop++)
+                               toksize += RND(token->k5->addresses[loop].data_len);
+
+                       toksize += 4 + RND(token->k5->ticket_len);
+                       toksize += 4 + RND(token->k5->ticket2_len);
+
+                       toksize += 4 + token->k5->n_authdata * 8;
+                       for (loop = 0; loop < token->k5->n_authdata; loop++)
+                               toksize += RND(token->k5->authdata[loop].data_len);
+                       break;
+
+               default: /* we have a ticket we can't encode */
+                       BUG();
+                       continue;
+               }
+
+               _debug("token[%u]: toksize=%u", ntoks, toksize);
+               ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
+
+               toksizes[ntoks++] = toksize;
+               size += toksize + 4; /* each token has a length word */
+       }
+
+#undef RND
+
+       if (!buffer || buflen < size)
+               return size;
+
+       xdr = (__be32 __user *) buffer;
+       zero = 0;
+#define ENCODE(x)                              \
+       do {                                    \
+               __be32 y = htonl(x);            \
+               if (put_user(y, xdr++) < 0)     \
+                       goto fault;             \
+       } while(0)
+#define ENCODE_DATA(l, s)                                              \
+       do {                                                            \
+               u32 _l = (l);                                           \
+               ENCODE(l);                                              \
+               if (copy_to_user(xdr, (s), _l) != 0)                    \
+                       goto fault;                                     \
+               if (_l & 3 &&                                           \
+                   copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \
+                       goto fault;                                     \
+               xdr += (_l + 3) >> 2;                                   \
+       } while(0)
+#define ENCODE64(x)                                    \
+       do {                                            \
+               __be64 y = cpu_to_be64(x);              \
+               if (copy_to_user(xdr, &y, 8) != 0)      \
+                       goto fault;                     \
+               xdr += 8 >> 2;                          \
+       } while(0)
+#define ENCODE_STR(s)                          \
+       do {                                    \
+               const char *_s = (s);           \
+               ENCODE_DATA(strlen(_s), _s);    \
+       } while(0)
+
+       ENCODE(0);                                      /* flags */
+       ENCODE_DATA(cnlen, key->description + 4);       /* cellname */
+       ENCODE(ntoks);
+
+       tok = 0;
+       for (token = key->payload.data; token; token = token->next) {
+               toksize = toksizes[tok++];
+               ENCODE(toksize);
+               oldxdr = xdr;
+               ENCODE(token->security_index);
+
+               switch (token->security_index) {
+               case RXRPC_SECURITY_RXKAD:
+                       ENCODE(token->kad->vice_id);
+                       ENCODE(token->kad->kvno);
+                       ENCODE_DATA(8, token->kad->session_key);
+                       ENCODE(token->kad->start);
+                       ENCODE(token->kad->expiry);
+                       ENCODE(token->kad->primary_flag);
+                       ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
+                       break;
+
+               case RXRPC_SECURITY_RXK5:
+                       princ = &token->k5->client;
+                       ENCODE(princ->n_name_parts);
+                       for (loop = 0; loop < princ->n_name_parts; loop++)
+                               ENCODE_STR(princ->name_parts[loop]);
+                       ENCODE_STR(princ->realm);
+
+                       princ = &token->k5->server;
+                       ENCODE(princ->n_name_parts);
+                       for (loop = 0; loop < princ->n_name_parts; loop++)
+                               ENCODE_STR(princ->name_parts[loop]);
+                       ENCODE_STR(princ->realm);
+
+                       ENCODE(token->k5->session.tag);
+                       ENCODE_DATA(token->k5->session.data_len,
+                                   token->k5->session.data);
+
+                       ENCODE64(token->k5->authtime);
+                       ENCODE64(token->k5->starttime);
+                       ENCODE64(token->k5->endtime);
+                       ENCODE64(token->k5->renew_till);
+                       ENCODE(token->k5->is_skey);
+                       ENCODE(token->k5->flags);
+
+                       ENCODE(token->k5->n_addresses);
+                       for (loop = 0; loop < token->k5->n_addresses; loop++) {
+                               ENCODE(token->k5->addresses[loop].tag);
+                               ENCODE_DATA(token->k5->addresses[loop].data_len,
+                                           token->k5->addresses[loop].data);
+                       }
+
+                       ENCODE_DATA(token->k5->ticket_len, token->k5->ticket);
+                       ENCODE_DATA(token->k5->ticket2_len, token->k5->ticket2);
+
+                       ENCODE(token->k5->n_authdata);
+                       for (loop = 0; loop < token->k5->n_authdata; loop++) {
+                               ENCODE(token->k5->authdata[loop].tag);
+                               ENCODE_DATA(token->k5->authdata[loop].data_len,
+                                           token->k5->authdata[loop].data);
+                       }
+                       break;
+
+               default:
+                       BUG();
+                       break;
+               }
+
+               ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
+                         toksize);
+       }
+
+#undef ENCODE_STR
+#undef ENCODE_DATA
+#undef ENCODE64
+#undef ENCODE
+
+       ASSERTCMP(tok, ==, ntoks);
+       ASSERTCMP((char __user *) xdr - buffer, ==, size);
+       _leave(" = %zu", size);
+       return size;
+
+fault:
+       _leave(" = -EFAULT");
+       return -EFAULT;
+}
index dc62920ee19ad5a430f5c6361bc01119f1746def..49b3cc31ee1f505b65bf21f6042e6727e2d2ed93 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/crypto.h>
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
+#include <keys/rxrpc-type.h>
 #include "ar-internal.h"
 
 static LIST_HEAD(rxrpc_security_methods);
@@ -122,6 +123,7 @@ EXPORT_SYMBOL_GPL(rxrpc_unregister_security);
  */
 int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
 {
+       struct rxrpc_key_token *token;
        struct rxrpc_security *sec;
        struct key *key = conn->key;
        int ret;
@@ -135,7 +137,11 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
        if (ret < 0)
                return ret;
 
-       sec = rxrpc_security_lookup(key->type_data.x[0]);
+       if (!key->payload.data)
+               return -EKEYREJECTED;
+       token = key->payload.data;
+
+       sec = rxrpc_security_lookup(token->security_index);
        if (!sec)
                return -EKEYREJECTED;
        conn->security = sec;
index ef8f91030a150ff6cb4605c8229dd1955b3528e0..713ac593e2e96d5a21b43958ff3ebb67816a8a3c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ctype.h>
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
+#include <keys/rxrpc-type.h>
 #define rxrpc_debug rxkad_debug
 #include "ar-internal.h"
 
@@ -42,7 +43,7 @@ struct rxkad_level2_hdr {
        __be32  checksum;       /* decrypted data checksum */
 };
 
-MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos)");
+MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos 4)");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
@@ -59,14 +60,14 @@ static DEFINE_MUTEX(rxkad_ci_mutex);
  */
 static int rxkad_init_connection_security(struct rxrpc_connection *conn)
 {
-       struct rxrpc_key_payload *payload;
        struct crypto_blkcipher *ci;
+       struct rxrpc_key_token *token;
        int ret;
 
        _enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
 
-       payload = conn->key->payload.data;
-       conn->security_ix = payload->k.security_index;
+       token = conn->key->payload.data;
+       conn->security_ix = token->security_index;
 
        ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(ci)) {
@@ -75,8 +76,8 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn)
                goto error;
        }
 
-       if (crypto_blkcipher_setkey(ci, payload->k.session_key,
-                                   sizeof(payload->k.session_key)) < 0)
+       if (crypto_blkcipher_setkey(ci, token->kad->session_key,
+                                   sizeof(token->kad->session_key)) < 0)
                BUG();
 
        switch (conn->security_level) {
@@ -110,7 +111,7 @@ error:
  */
 static void rxkad_prime_packet_security(struct rxrpc_connection *conn)
 {
-       struct rxrpc_key_payload *payload;
+       struct rxrpc_key_token *token;
        struct blkcipher_desc desc;
        struct scatterlist sg[2];
        struct rxrpc_crypt iv;
@@ -123,8 +124,8 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn)
        if (!conn->key)
                return;
 
-       payload = conn->key->payload.data;
-       memcpy(&iv, payload->k.session_key, sizeof(iv));
+       token = conn->key->payload.data;
+       memcpy(&iv, token->kad->session_key, sizeof(iv));
 
        desc.tfm = conn->cipher;
        desc.info = iv.x;
@@ -197,7 +198,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
                                        u32 data_size,
                                        void *sechdr)
 {
-       const struct rxrpc_key_payload *payload;
+       const struct rxrpc_key_token *token;
        struct rxkad_level2_hdr rxkhdr
                __attribute__((aligned(8))); /* must be all on one page */
        struct rxrpc_skb_priv *sp;
@@ -219,8 +220,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
        rxkhdr.checksum = 0;
 
        /* encrypt from the session key */
-       payload = call->conn->key->payload.data;
-       memcpy(&iv, payload->k.session_key, sizeof(iv));
+       token = call->conn->key->payload.data;
+       memcpy(&iv, token->kad->session_key, sizeof(iv));
        desc.tfm = call->conn->cipher;
        desc.info = iv.x;
        desc.flags = 0;
@@ -400,7 +401,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
                                       struct sk_buff *skb,
                                       u32 *_abort_code)
 {
-       const struct rxrpc_key_payload *payload;
+       const struct rxrpc_key_token *token;
        struct rxkad_level2_hdr sechdr;
        struct rxrpc_skb_priv *sp;
        struct blkcipher_desc desc;
@@ -431,8 +432,8 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
        skb_to_sgvec(skb, sg, 0, skb->len);
 
        /* decrypt from the session key */
-       payload = call->conn->key->payload.data;
-       memcpy(&iv, payload->k.session_key, sizeof(iv));
+       token = call->conn->key->payload.data;
+       memcpy(&iv, token->kad->session_key, sizeof(iv));
        desc.tfm = call->conn->cipher;
        desc.info = iv.x;
        desc.flags = 0;
@@ -506,7 +507,7 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
        if (!call->conn->cipher)
                return 0;
 
-       if (sp->hdr.securityIndex != 2) {
+       if (sp->hdr.securityIndex != RXRPC_SECURITY_RXKAD) {
                *_abort_code = RXKADINCONSISTENCY;
                _leave(" = -EPROTO [not rxkad]");
                return -EPROTO;
@@ -737,7 +738,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
                                      struct sk_buff *skb,
                                      u32 *_abort_code)
 {
-       const struct rxrpc_key_payload *payload;
+       const struct rxrpc_key_token *token;
        struct rxkad_challenge challenge;
        struct rxkad_response resp
                __attribute__((aligned(8))); /* must be aligned for crypto */
@@ -778,7 +779,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
        if (conn->security_level < min_level)
                goto protocol_error;
 
-       payload = conn->key->payload.data;
+       token = conn->key->payload.data;
 
        /* build the response packet */
        memset(&resp, 0, sizeof(resp));
@@ -797,13 +798,13 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
                (conn->channels[3] ? conn->channels[3]->call_id : 0);
        resp.encrypted.inc_nonce = htonl(nonce + 1);
        resp.encrypted.level = htonl(conn->security_level);
-       resp.kvno = htonl(payload->k.kvno);
-       resp.ticket_len = htonl(payload->k.ticket_len);
+       resp.kvno = htonl(token->kad->kvno);
+       resp.ticket_len = htonl(token->kad->ticket_len);
 
        /* calculate the response checksum and then do the encryption */
        rxkad_calc_response_checksum(&resp);
-       rxkad_encrypt_response(conn, &resp, &payload->k);
-       return rxkad_send_response(conn, &sp->hdr, &resp, &payload->k);
+       rxkad_encrypt_response(conn, &resp, token->kad);
+       return rxkad_send_response(conn, &sp->hdr, &resp, token->kad);
 
 protocol_error:
        *_abort_code = abort_code;
@@ -1122,7 +1123,7 @@ static void rxkad_clear(struct rxrpc_connection *conn)
 static struct rxrpc_security rxkad = {
        .owner                          = THIS_MODULE,
        .name                           = "rxkad",
-       .security_index                 = RXKAD_VERSION,
+       .security_index                 = RXRPC_SECURITY_RXKAD,
        .init_connection_security       = rxkad_init_connection_security,
        .prime_packet_security          = rxkad_prime_packet_security,
        .secure_packet                  = rxkad_secure_packet,
index 692d9a41cd23e714f77eda461323962e11c3a7b8..903e4188b6ca1057426f8327f0bb1d69f00afb0b 100644 (file)
@@ -693,13 +693,18 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                        if (new && i > 0)
                                atomic_inc(&new->refcnt);
 
-                       qdisc_destroy(old);
+                       if (!ingress)
+                               qdisc_destroy(old);
                }
 
-               notify_and_destroy(skb, n, classid, dev->qdisc, new);
-               if (new && !new->ops->attach)
-                       atomic_inc(&new->refcnt);
-               dev->qdisc = new ? : &noop_qdisc;
+               if (!ingress) {
+                       notify_and_destroy(skb, n, classid, dev->qdisc, new);
+                       if (new && !new->ops->attach)
+                               atomic_inc(&new->refcnt);
+                       dev->qdisc = new ? : &noop_qdisc;
+               } else {
+                       notify_and_destroy(skb, n, classid, old, new);
+               }
 
                if (dev->flags & IFF_UP)
                        dev_activate(dev);
@@ -804,7 +809,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
                        stab = qdisc_get_stab(tca[TCA_STAB]);
                        if (IS_ERR(stab)) {
                                err = PTR_ERR(stab);
-                               goto err_out3;
+                               goto err_out4;
                        }
                        sch->stab = stab;
                }
@@ -833,7 +838,6 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
                return sch;
        }
 err_out3:
-       qdisc_put_stab(sch->stab);
        dev_put(dev);
        kfree((char *) sch - sch->padded);
 err_out2:
@@ -847,6 +851,7 @@ err_out4:
         * Any broken qdiscs that would require a ops->reset() here?
         * The qdisc was never in action so it shouldn't be necessary.
         */
+       qdisc_put_stab(sch->stab);
        if (ops->destroy)
                ops->destroy(sch);
        goto err_out3;
@@ -1111,12 +1116,16 @@ create_n_graft:
                                 tcm->tcm_parent, tcm->tcm_parent,
                                 tca, &err);
        else {
-               unsigned int ntx = 0;
+               struct netdev_queue *dev_queue;
 
                if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
-                       ntx = p->ops->cl_ops->select_queue(p, tcm);
+                       dev_queue = p->ops->cl_ops->select_queue(p, tcm);
+               else if (p)
+                       dev_queue = p->dev_queue;
+               else
+                       dev_queue = netdev_get_tx_queue(dev, 0);
 
-               q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
+               q = qdisc_create(dev, dev_queue, p,
                                 tcm->tcm_parent, tcm->tcm_handle,
                                 tca, &err);
        }
index 12b2fb04b29b6d4d873e6fe28981dabd7de039b6..5a888af7e5daed2f46d3293a843de8182f3f6cc3 100644 (file)
@@ -274,8 +274,10 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
        struct tc_drr_stats xstats;
 
        memset(&xstats, 0, sizeof(xstats));
-       if (cl->qdisc->q.qlen)
+       if (cl->qdisc->q.qlen) {
                xstats.deficit = cl->deficit;
+               cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
+       }
 
        if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
index dd5ee022f1f7c1d76b28b4fd76028880db6ecaa5..d1dea3d5dc929f1dc2051b2ed42f65168c88aa09 100644 (file)
@@ -125,13 +125,18 @@ static struct netdev_queue *mq_queue_get(struct Qdisc *sch, unsigned long cl)
        return netdev_get_tx_queue(dev, ntx);
 }
 
-static unsigned int mq_select_queue(struct Qdisc *sch, struct tcmsg *tcm)
+static struct netdev_queue *mq_select_queue(struct Qdisc *sch,
+                                           struct tcmsg *tcm)
 {
        unsigned int ntx = TC_H_MIN(tcm->tcm_parent);
+       struct netdev_queue *dev_queue = mq_queue_get(sch, ntx);
 
-       if (!mq_queue_get(sch, ntx))
-               return 0;
-       return ntx - 1;
+       if (!dev_queue) {
+               struct net_device *dev = qdisc_dev(sch);
+
+               return netdev_get_tx_queue(dev, 0);
+       }
+       return dev_queue;
 }
 
 static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
@@ -188,6 +193,7 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
        struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
 
        sch = dev_queue->qdisc_sleeping;
+       sch->qstats.qlen = sch->q.qlen;
        if (gnet_stats_copy_basic(d, &sch->bstats) < 0 ||
            gnet_stats_copy_queue(d, &sch->qstats) < 0)
                return -1;
index 069f81c972778cda6f26b4c276b6b1495f10da5b..7db2c88ce585f04a7361b87dec3aa2760d65f1f3 100644 (file)
@@ -359,6 +359,7 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
        struct Qdisc *cl_q;
 
        cl_q = q->queues[cl - 1];
+       cl_q->qstats.qlen = cl_q->q.qlen;
        if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
            gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
                return -1;
index 0f73c412d04b6005091fc69b0fb068a3e94bb662..93285cecb246942b5640809d34e7d17d9ee1d63a 100644 (file)
@@ -322,6 +322,7 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
        struct Qdisc *cl_q;
 
        cl_q = q->queues[cl - 1];
+       cl_q->qstats.qlen = cl_q->q.qlen;
        if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
            gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
                return -1;
index 6a4b19094143653ab79a43de52d916fd8ed2a0f0..bb280e60e00a9f23c93ae1047ef1934af62ad81c 100644 (file)
@@ -949,7 +949,7 @@ static int sctp6_rcv(struct sk_buff *skb)
        return sctp_rcv(skb) ? -1 : 0;
 }
 
-static struct inet6_protocol sctpv6_protocol = {
+static const struct inet6_protocol sctpv6_protocol = {
        .handler      = sctp6_rcv,
        .err_handler  = sctp_v6_err,
        .flags        = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
index 60093be8385d68fa27ba002e6c84e51db437a2dd..c557f1fb1c66ac79647ff91cf80f72c59e0baf05 100644 (file)
@@ -924,7 +924,7 @@ static struct inet_protosw sctp_stream_protosw = {
 };
 
 /* Register with IP layer.  */
-static struct net_protocol sctp_protocol = {
+static const struct net_protocol sctp_protocol = {
        .handler     = sctp_rcv,
        .err_handler = sctp_v4_err,
        .no_policy   = 1,
index 6d47165590473daa4990bf69b0435d5c49b41302..2a022c00d85c509e2346a8afac33eaa63154439a 100644 (file)
@@ -489,6 +489,7 @@ static struct socket *sock_alloc(void)
 
        sock = SOCKET_I(inode);
 
+       kmemcheck_annotate_bitfield(sock, type);
        inode->i_mode = S_IFSOCK | S_IRWXUGO;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();