diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-09-19 00:42:13 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-09-19 00:42:13 -0400 |
| commit | 4a3381feb823e06c8e2da7e283c17b0b6fdbddcf (patch) | |
| tree | e1bef4c3db854bb10fd13dc67415d77b5d999533 /drivers | |
| parent | fea63e38013ec628ab3f7fddc4c2148064b7910a (diff) | |
| parent | 47a5c6fa0e204a2b63309c648bb2fde36836c826 (diff) | |
Merge branch 'master' into upstream
Diffstat (limited to 'drivers')
30 files changed, 594 insertions, 407 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bb66a12c84e5..e85c2f8cf193 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -1276,10 +1276,15 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
| 1276 | swap_buf_le16(id, ATA_ID_WORDS); | 1276 | swap_buf_le16(id, ATA_ID_WORDS); |
| 1277 | 1277 | ||
| 1278 | /* sanity check */ | 1278 | /* sanity check */ |
| 1279 | if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { | 1279 | rc = -EINVAL; |
| 1280 | rc = -EINVAL; | 1280 | reason = "device reports illegal type"; |
| 1281 | reason = "device reports illegal type"; | 1281 | |
| 1282 | goto err_out; | 1282 | if (class == ATA_DEV_ATA) { |
| 1283 | if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) | ||
| 1284 | goto err_out; | ||
| 1285 | } else { | ||
| 1286 | if (ata_id_is_ata(id)) | ||
| 1287 | goto err_out; | ||
| 1283 | } | 1288 | } |
| 1284 | 1289 | ||
| 1285 | if (post_reset && class == ATA_DEV_ATA) { | 1290 | if (post_reset && class == ATA_DEV_ATA) { |
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index d369130f4235..dd96123a2b7f 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c | |||
| @@ -2282,6 +2282,8 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) | |||
| 2282 | TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); | 2282 | TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); |
| 2283 | 2283 | ||
| 2284 | if (new_tail == he_dev->tpdrq_head) { | 2284 | if (new_tail == he_dev->tpdrq_head) { |
| 2285 | int slot; | ||
| 2286 | |||
| 2285 | hprintk("tpdrq full (cid 0x%x)\n", cid); | 2287 | hprintk("tpdrq full (cid 0x%x)\n", cid); |
| 2286 | /* | 2288 | /* |
| 2287 | * FIXME | 2289 | * FIXME |
| @@ -2289,6 +2291,13 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) | |||
| 2289 | * after service_tbrq, service the backlog | 2291 | * after service_tbrq, service the backlog |
| 2290 | * for now, we just drop the pdu | 2292 | * for now, we just drop the pdu |
| 2291 | */ | 2293 | */ |
| 2294 | for (slot = 0; slot < TPD_MAXIOV; ++slot) { | ||
| 2295 | if (tpd->iovec[slot].addr) | ||
| 2296 | pci_unmap_single(he_dev->pci_dev, | ||
| 2297 | tpd->iovec[slot].addr, | ||
| 2298 | tpd->iovec[slot].len & TPD_LEN_MASK, | ||
| 2299 | PCI_DMA_TODEVICE); | ||
| 2300 | } | ||
| 2292 | if (tpd->skb) { | 2301 | if (tpd->skb) { |
| 2293 | if (tpd->vcc->pop) | 2302 | if (tpd->vcc->pop) |
| 2294 | tpd->vcc->pop(tpd->vcc, tpd->skb); | 2303 | tpd->vcc->pop(tpd->vcc, tpd->skb); |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 7b0eca703a67..2cd3391ff878 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -48,14 +48,14 @@ | |||
| 48 | #include <linux/completion.h> | 48 | #include <linux/completion.h> |
| 49 | 49 | ||
| 50 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) | 50 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) |
| 51 | #define DRIVER_NAME "HP CISS Driver (v 2.6.10)" | 51 | #define DRIVER_NAME "HP CISS Driver (v 3.6.10)" |
| 52 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10) | 52 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,10) |
| 53 | 53 | ||
| 54 | /* Embedded module documentation macros - see modules.h */ | 54 | /* Embedded module documentation macros - see modules.h */ |
| 55 | MODULE_AUTHOR("Hewlett-Packard Company"); | 55 | MODULE_AUTHOR("Hewlett-Packard Company"); |
| 56 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10"); | 56 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.10"); |
| 57 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" | 57 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" |
| 58 | " SA6i P600 P800 P400 P400i E200 E200i"); | 58 | " SA6i P600 P800 P400 P400i E200 E200i E500"); |
| 59 | MODULE_LICENSE("GPL"); | 59 | MODULE_LICENSE("GPL"); |
| 60 | 60 | ||
| 61 | #include "cciss_cmd.h" | 61 | #include "cciss_cmd.h" |
| @@ -82,6 +82,7 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
| 82 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213}, | 82 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213}, |
| 83 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214}, | 83 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214}, |
| 84 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, | 84 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, |
| 85 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3233}, | ||
| 85 | {0,} | 86 | {0,} |
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| @@ -110,6 +111,7 @@ static struct board_type products[] = { | |||
| 110 | {0x3213103C, "Smart Array E200i", &SA5_access}, | 111 | {0x3213103C, "Smart Array E200i", &SA5_access}, |
| 111 | {0x3214103C, "Smart Array E200i", &SA5_access}, | 112 | {0x3214103C, "Smart Array E200i", &SA5_access}, |
| 112 | {0x3215103C, "Smart Array E200i", &SA5_access}, | 113 | {0x3215103C, "Smart Array E200i", &SA5_access}, |
| 114 | {0x3233103C, "Smart Array E500", &SA5_access}, | ||
| 113 | }; | 115 | }; |
| 114 | 116 | ||
| 115 | /* How long to wait (in milliseconds) for board to go into simple mode */ | 117 | /* How long to wait (in milliseconds) for board to go into simple mode */ |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index ca2f538e549e..613d67f1c7f0 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -668,6 +668,7 @@ int khvcd(void *unused) | |||
| 668 | do { | 668 | do { |
| 669 | poll_mask = 0; | 669 | poll_mask = 0; |
| 670 | hvc_kicked = 0; | 670 | hvc_kicked = 0; |
| 671 | try_to_freeze(); | ||
| 671 | wmb(); | 672 | wmb(); |
| 672 | if (cpus_empty(cpus_in_xmon)) { | 673 | if (cpus_empty(cpus_in_xmon)) { |
| 673 | spin_lock(&hvc_structs_lock); | 674 | spin_lock(&hvc_structs_lock); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f57eba0bf253..abca98beac14 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -402,10 +402,10 @@ static void handle_flags(struct smi_info *smi_info) | |||
| 402 | smi_info->curr_msg->data, | 402 | smi_info->curr_msg->data, |
| 403 | smi_info->curr_msg->data_size); | 403 | smi_info->curr_msg->data_size); |
| 404 | smi_info->si_state = SI_GETTING_EVENTS; | 404 | smi_info->si_state = SI_GETTING_EVENTS; |
| 405 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { | 405 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL && |
| 406 | if (smi_info->oem_data_avail_handler) | 406 | smi_info->oem_data_avail_handler) { |
| 407 | if (smi_info->oem_data_avail_handler(smi_info)) | 407 | if (smi_info->oem_data_avail_handler(smi_info)) |
| 408 | goto retry; | 408 | goto retry; |
| 409 | } else { | 409 | } else { |
| 410 | smi_info->si_state = SI_NORMAL; | 410 | smi_info->si_state = SI_NORMAL; |
| 411 | } | 411 | } |
| @@ -2481,6 +2481,7 @@ static __devinit int init_ipmi_si(void) | |||
| 2481 | #ifdef CONFIG_PCI | 2481 | #ifdef CONFIG_PCI |
| 2482 | pci_unregister_driver(&ipmi_pci_driver); | 2482 | pci_unregister_driver(&ipmi_pci_driver); |
| 2483 | #endif | 2483 | #endif |
| 2484 | driver_unregister(&ipmi_driver); | ||
| 2484 | printk("ipmi_si: Unable to find any System Interface(s)\n"); | 2485 | printk("ipmi_si: Unable to find any System Interface(s)\n"); |
| 2485 | return -ENODEV; | 2486 | return -ENODEV; |
| 2486 | } else { | 2487 | } else { |
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 351dab2fcacf..d419e4bb54f4 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c | |||
| @@ -730,7 +730,7 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif) | |||
| 730 | 730 | ||
| 731 | if(m5229_revision <= 0x20) | 731 | if(m5229_revision <= 0x20) |
| 732 | tmpbyte = (tmpbyte & (~0x02)) | 0x01; | 732 | tmpbyte = (tmpbyte & (~0x02)) | 0x01; |
| 733 | else if (m5229_revision == 0xc7) | 733 | else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) |
| 734 | tmpbyte |= 0x03; | 734 | tmpbyte |= 0x03; |
| 735 | else | 735 | else |
| 736 | tmpbyte |= 0x01; | 736 | tmpbyte |= 0x01; |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d6f99d5720fc..5d625a81193f 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
| @@ -49,7 +49,7 @@ MODULE_DESCRIPTION("Generic RDMA CM Agent"); | |||
| 49 | MODULE_LICENSE("Dual BSD/GPL"); | 49 | MODULE_LICENSE("Dual BSD/GPL"); |
| 50 | 50 | ||
| 51 | #define CMA_CM_RESPONSE_TIMEOUT 20 | 51 | #define CMA_CM_RESPONSE_TIMEOUT 20 |
| 52 | #define CMA_MAX_CM_RETRIES 3 | 52 | #define CMA_MAX_CM_RETRIES 15 |
| 53 | 53 | ||
| 54 | static void cma_add_one(struct ib_device *device); | 54 | static void cma_add_one(struct ib_device *device); |
| 55 | static void cma_remove_one(struct ib_device *device); | 55 | static void cma_remove_one(struct ib_device *device); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index b5e6a7be603d..ec356ce7cdcd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -326,6 +326,7 @@ ipoib_mcast_sendonly_join_complete(int status, | |||
| 326 | 326 | ||
| 327 | /* Clear the busy flag so we try again */ | 327 | /* Clear the busy flag so we try again */ |
| 328 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | 328 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
| 329 | mcast->query = NULL; | ||
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | complete(&mcast->done); | 332 | complete(&mcast->done); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 8257d5a2c8f8..fd8344cdc0db 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -799,13 +799,6 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) | |||
| 799 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); | 799 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); |
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | static void srp_reconnect_work(void *target_ptr) | ||
| 803 | { | ||
| 804 | struct srp_target_port *target = target_ptr; | ||
| 805 | |||
| 806 | srp_reconnect_target(target); | ||
| 807 | } | ||
| 808 | |||
| 809 | static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) | 802 | static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) |
| 810 | { | 803 | { |
| 811 | struct srp_iu *iu; | 804 | struct srp_iu *iu; |
| @@ -858,7 +851,6 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) | |||
| 858 | { | 851 | { |
| 859 | struct srp_target_port *target = target_ptr; | 852 | struct srp_target_port *target = target_ptr; |
| 860 | struct ib_wc wc; | 853 | struct ib_wc wc; |
| 861 | unsigned long flags; | ||
| 862 | 854 | ||
| 863 | ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); | 855 | ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); |
| 864 | while (ib_poll_cq(cq, 1, &wc) > 0) { | 856 | while (ib_poll_cq(cq, 1, &wc) > 0) { |
| @@ -866,10 +858,6 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) | |||
| 866 | printk(KERN_ERR PFX "failed %s status %d\n", | 858 | printk(KERN_ERR PFX "failed %s status %d\n", |
| 867 | wc.wr_id & SRP_OP_RECV ? "receive" : "send", | 859 | wc.wr_id & SRP_OP_RECV ? "receive" : "send", |
| 868 | wc.status); | 860 | wc.status); |
| 869 | spin_lock_irqsave(target->scsi_host->host_lock, flags); | ||
| 870 | if (target->state == SRP_TARGET_LIVE) | ||
| 871 | schedule_work(&target->work); | ||
| 872 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); | ||
| 873 | break; | 861 | break; |
| 874 | } | 862 | } |
| 875 | 863 | ||
| @@ -1705,8 +1693,6 @@ static ssize_t srp_create_target(struct class_device *class_dev, | |||
| 1705 | target->scsi_host = target_host; | 1693 | target->scsi_host = target_host; |
| 1706 | target->srp_host = host; | 1694 | target->srp_host = host; |
| 1707 | 1695 | ||
| 1708 | INIT_WORK(&target->work, srp_reconnect_work, target); | ||
| 1709 | |||
| 1710 | INIT_LIST_HEAD(&target->free_reqs); | 1696 | INIT_LIST_HEAD(&target->free_reqs); |
| 1711 | INIT_LIST_HEAD(&target->req_queue); | 1697 | INIT_LIST_HEAD(&target->req_queue); |
| 1712 | for (i = 0; i < SRP_SQ_SIZE; ++i) { | 1698 | for (i = 0; i < SRP_SQ_SIZE; ++i) { |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c8cbc00243fe..0a54d003ef34 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -1204,7 +1204,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
| 1204 | pos = steps * (eccsize + chunk); | 1204 | pos = steps * (eccsize + chunk); |
| 1205 | steps = 0; | 1205 | steps = 0; |
| 1206 | } else | 1206 | } else |
| 1207 | pos = eccsize + chunk; | 1207 | pos = eccsize; |
| 1208 | 1208 | ||
| 1209 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); | 1209 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); |
| 1210 | for (i = 0; i < steps; i++) { | 1210 | for (i = 0; i < steps; i++) { |
| @@ -1567,7 +1567,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, | |||
| 1567 | bytes = min_t(size_t, len, free->length); | 1567 | bytes = min_t(size_t, len, free->length); |
| 1568 | boffs = free->offset; | 1568 | boffs = free->offset; |
| 1569 | } | 1569 | } |
| 1570 | memcpy(chip->oob_poi + woffs, oob, bytes); | 1570 | memcpy(chip->oob_poi + boffs, oob, bytes); |
| 1571 | oob += bytes; | 1571 | oob += bytes; |
| 1572 | } | 1572 | } |
| 1573 | return oob; | 1573 | return oob; |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 726f43d55937..98ef9f85482f 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -1433,8 +1433,8 @@ e1000_configure_tx(struct e1000_adapter *adapter) | |||
| 1433 | E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); | 1433 | E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); |
| 1434 | E1000_WRITE_REG(hw, TDT, 0); | 1434 | E1000_WRITE_REG(hw, TDT, 0); |
| 1435 | E1000_WRITE_REG(hw, TDH, 0); | 1435 | E1000_WRITE_REG(hw, TDH, 0); |
| 1436 | adapter->tx_ring[0].tdh = E1000_TDH; | 1436 | adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH); |
| 1437 | adapter->tx_ring[0].tdt = E1000_TDT; | 1437 | adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT); |
| 1438 | break; | 1438 | break; |
| 1439 | } | 1439 | } |
| 1440 | 1440 | ||
| @@ -1840,8 +1840,8 @@ e1000_configure_rx(struct e1000_adapter *adapter) | |||
| 1840 | E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); | 1840 | E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); |
| 1841 | E1000_WRITE_REG(hw, RDT, 0); | 1841 | E1000_WRITE_REG(hw, RDT, 0); |
| 1842 | E1000_WRITE_REG(hw, RDH, 0); | 1842 | E1000_WRITE_REG(hw, RDH, 0); |
| 1843 | adapter->rx_ring[0].rdh = E1000_RDH; | 1843 | adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH); |
| 1844 | adapter->rx_ring[0].rdt = E1000_RDT; | 1844 | adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT); |
| 1845 | break; | 1845 | break; |
| 1846 | } | 1846 | } |
| 1847 | 1847 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 760c61b98867..eeab1df5bef3 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -385,6 +385,8 @@ static int mv643xx_eth_receive_queue(struct net_device *dev, int budget) | |||
| 385 | struct pkt_info pkt_info; | 385 | struct pkt_info pkt_info; |
| 386 | 386 | ||
| 387 | while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { | 387 | while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { |
| 388 | dma_unmap_single(NULL, pkt_info.buf_ptr, RX_SKB_SIZE, | ||
| 389 | DMA_FROM_DEVICE); | ||
| 388 | mp->rx_desc_count--; | 390 | mp->rx_desc_count--; |
| 389 | received_packets++; | 391 | received_packets++; |
| 390 | 392 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index da9d06bdb818..aa792821854e 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
| @@ -1430,9 +1430,43 @@ static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) | |||
| 1430 | break; | 1430 | break; |
| 1431 | } | 1431 | } |
| 1432 | 1432 | ||
| 1433 | switch (rate) { | ||
| 1434 | case ZD_OFDM_RATE_6M: | ||
| 1435 | case ZD_OFDM_RATE_9M: | ||
| 1436 | i += 3; | ||
| 1437 | break; | ||
| 1438 | case ZD_OFDM_RATE_12M: | ||
| 1439 | case ZD_OFDM_RATE_18M: | ||
| 1440 | i += 5; | ||
| 1441 | break; | ||
| 1442 | case ZD_OFDM_RATE_24M: | ||
| 1443 | case ZD_OFDM_RATE_36M: | ||
| 1444 | i += 9; | ||
| 1445 | break; | ||
| 1446 | case ZD_OFDM_RATE_48M: | ||
| 1447 | case ZD_OFDM_RATE_54M: | ||
| 1448 | i += 15; | ||
| 1449 | break; | ||
| 1450 | default: | ||
| 1451 | return -EINVAL; | ||
| 1452 | } | ||
| 1453 | |||
| 1433 | return i; | 1454 | return i; |
| 1434 | } | 1455 | } |
| 1435 | 1456 | ||
| 1457 | static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size) | ||
| 1458 | { | ||
| 1459 | int r; | ||
| 1460 | |||
| 1461 | r = ofdm_qual_db(status_quality, rate, size); | ||
| 1462 | ZD_ASSERT(r >= 0); | ||
| 1463 | if (r < 0) | ||
| 1464 | r = 0; | ||
| 1465 | |||
| 1466 | r = (r * 100)/29; | ||
| 1467 | return r <= 100 ? r : 100; | ||
| 1468 | } | ||
| 1469 | |||
| 1436 | static unsigned int log10times100(unsigned int x) | 1470 | static unsigned int log10times100(unsigned int x) |
| 1437 | { | 1471 | { |
| 1438 | static const u8 log10[] = { | 1472 | static const u8 log10[] = { |
| @@ -1476,31 +1510,28 @@ static int cck_snr_db(u8 status_quality) | |||
| 1476 | return r; | 1510 | return r; |
| 1477 | } | 1511 | } |
| 1478 | 1512 | ||
| 1479 | static int rx_qual_db(const void *rx_frame, unsigned int size, | 1513 | static int cck_qual_percent(u8 status_quality) |
| 1480 | const struct rx_status *status) | ||
| 1481 | { | 1514 | { |
| 1482 | return (status->frame_status&ZD_RX_OFDM) ? | 1515 | int r; |
| 1483 | ofdm_qual_db(status->signal_quality_ofdm, | 1516 | |
| 1484 | zd_ofdm_plcp_header_rate(rx_frame), | 1517 | r = cck_snr_db(status_quality); |
| 1485 | size) : | 1518 | r = (100*r)/17; |
| 1486 | cck_snr_db(status->signal_quality_cck); | 1519 | return r <= 100 ? r : 100; |
| 1487 | } | 1520 | } |
| 1488 | 1521 | ||
| 1489 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | 1522 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, |
| 1490 | const struct rx_status *status) | 1523 | const struct rx_status *status) |
| 1491 | { | 1524 | { |
| 1492 | int r = rx_qual_db(rx_frame, size, status); | 1525 | return (status->frame_status&ZD_RX_OFDM) ? |
| 1493 | if (r < 0) | 1526 | ofdm_qual_percent(status->signal_quality_ofdm, |
| 1494 | r = 0; | 1527 | zd_ofdm_plcp_header_rate(rx_frame), |
| 1495 | r = (r * 100) / 14; | 1528 | size) : |
| 1496 | if (r > 100) | 1529 | cck_qual_percent(status->signal_quality_cck); |
| 1497 | r = 100; | ||
| 1498 | return r; | ||
| 1499 | } | 1530 | } |
| 1500 | 1531 | ||
| 1501 | u8 zd_rx_strength_percent(u8 rssi) | 1532 | u8 zd_rx_strength_percent(u8 rssi) |
| 1502 | { | 1533 | { |
| 1503 | int r = (rssi*100) / 30; | 1534 | int r = (rssi*100) / 41; |
| 1504 | if (r > 100) | 1535 | if (r > 100) |
| 1505 | r = 100; | 1536 | r = 100; |
| 1506 | return (u8) r; | 1537 | return (u8) r; |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index d6f3e02a0b54..a9bd80a08613 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
| @@ -816,13 +816,25 @@ static int filter_rx(struct ieee80211_device *ieee, | |||
| 816 | return -EINVAL; | 816 | return -EINVAL; |
| 817 | } | 817 | } |
| 818 | 818 | ||
| 819 | static void update_qual_rssi(struct zd_mac *mac, u8 qual_percent, u8 rssi) | 819 | static void update_qual_rssi(struct zd_mac *mac, |
| 820 | const u8 *buffer, unsigned int length, | ||
| 821 | u8 qual_percent, u8 rssi_percent) | ||
| 820 | { | 822 | { |
| 821 | unsigned long flags; | 823 | unsigned long flags; |
| 824 | struct ieee80211_hdr_3addr *hdr; | ||
| 825 | int i; | ||
| 826 | |||
| 827 | hdr = (struct ieee80211_hdr_3addr *)buffer; | ||
| 828 | if (length < offsetof(struct ieee80211_hdr_3addr, addr3)) | ||
| 829 | return; | ||
| 830 | if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0) | ||
| 831 | return; | ||
| 822 | 832 | ||
| 823 | spin_lock_irqsave(&mac->lock, flags); | 833 | spin_lock_irqsave(&mac->lock, flags); |
| 824 | mac->qual_average = (7 * mac->qual_average + qual_percent) / 8; | 834 | i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE; |
| 825 | mac->rssi_average = (7 * mac->rssi_average + rssi) / 8; | 835 | mac->qual_buffer[i] = qual_percent; |
| 836 | mac->rssi_buffer[i] = rssi_percent; | ||
| 837 | mac->stats_count++; | ||
| 826 | spin_unlock_irqrestore(&mac->lock, flags); | 838 | spin_unlock_irqrestore(&mac->lock, flags); |
| 827 | } | 839 | } |
| 828 | 840 | ||
| @@ -853,7 +865,6 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats, | |||
| 853 | if (stats->rate) | 865 | if (stats->rate) |
| 854 | stats->mask |= IEEE80211_STATMASK_RATE; | 866 | stats->mask |= IEEE80211_STATMASK_RATE; |
| 855 | 867 | ||
| 856 | update_qual_rssi(mac, stats->signal, stats->rssi); | ||
| 857 | return 0; | 868 | return 0; |
| 858 | } | 869 | } |
| 859 | 870 | ||
| @@ -877,6 +888,8 @@ int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) | |||
| 877 | sizeof(struct rx_status); | 888 | sizeof(struct rx_status); |
| 878 | buffer += ZD_PLCP_HEADER_SIZE; | 889 | buffer += ZD_PLCP_HEADER_SIZE; |
| 879 | 890 | ||
| 891 | update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi); | ||
| 892 | |||
| 880 | r = filter_rx(ieee, buffer, length, &stats); | 893 | r = filter_rx(ieee, buffer, length, &stats); |
| 881 | if (r <= 0) | 894 | if (r <= 0) |
| 882 | return r; | 895 | return r; |
| @@ -981,17 +994,31 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | |||
| 981 | { | 994 | { |
| 982 | struct zd_mac *mac = zd_netdev_mac(ndev); | 995 | struct zd_mac *mac = zd_netdev_mac(ndev); |
| 983 | struct iw_statistics *iw_stats = &mac->iw_stats; | 996 | struct iw_statistics *iw_stats = &mac->iw_stats; |
| 997 | unsigned int i, count, qual_total, rssi_total; | ||
| 984 | 998 | ||
| 985 | memset(iw_stats, 0, sizeof(struct iw_statistics)); | 999 | memset(iw_stats, 0, sizeof(struct iw_statistics)); |
| 986 | /* We are not setting the status, because ieee->state is not updated | 1000 | /* We are not setting the status, because ieee->state is not updated |
| 987 | * at all and this driver doesn't track authentication state. | 1001 | * at all and this driver doesn't track authentication state. |
| 988 | */ | 1002 | */ |
| 989 | spin_lock_irq(&mac->lock); | 1003 | spin_lock_irq(&mac->lock); |
| 990 | iw_stats->qual.qual = mac->qual_average; | 1004 | count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ? |
| 991 | iw_stats->qual.level = mac->rssi_average; | 1005 | mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE; |
| 992 | iw_stats->qual.updated = IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED| | 1006 | qual_total = rssi_total = 0; |
| 993 | IW_QUAL_NOISE_INVALID; | 1007 | for (i = 0; i < count; i++) { |
| 1008 | qual_total += mac->qual_buffer[i]; | ||
| 1009 | rssi_total += mac->rssi_buffer[i]; | ||
| 1010 | } | ||
| 994 | spin_unlock_irq(&mac->lock); | 1011 | spin_unlock_irq(&mac->lock); |
| 1012 | iw_stats->qual.updated = IW_QUAL_NOISE_INVALID; | ||
| 1013 | if (count > 0) { | ||
| 1014 | iw_stats->qual.qual = qual_total / count; | ||
| 1015 | iw_stats->qual.level = rssi_total / count; | ||
| 1016 | iw_stats->qual.updated |= | ||
| 1017 | IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED; | ||
| 1018 | } else { | ||
| 1019 | iw_stats->qual.updated |= | ||
| 1020 | IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID; | ||
| 1021 | } | ||
| 995 | /* TODO: update counter */ | 1022 | /* TODO: update counter */ |
| 996 | return iw_stats; | 1023 | return iw_stats; |
| 997 | } | 1024 | } |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 71e382c589ee..b3ba49b84634 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* zd_mac.c | 1 | /* zd_mac.h |
| 2 | * | 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify | 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License as published by | 4 | * it under the terms of the GNU General Public License as published by |
| @@ -87,9 +87,9 @@ struct rx_length_info { | |||
| 87 | #define RX_LENGTH_INFO_TAG 0x697e | 87 | #define RX_LENGTH_INFO_TAG 0x697e |
| 88 | 88 | ||
| 89 | struct rx_status { | 89 | struct rx_status { |
| 90 | u8 signal_quality_cck; | ||
| 90 | /* rssi */ | 91 | /* rssi */ |
| 91 | u8 signal_strength; | 92 | u8 signal_strength; |
| 92 | u8 signal_quality_cck; | ||
| 93 | u8 signal_quality_ofdm; | 93 | u8 signal_quality_ofdm; |
| 94 | u8 decryption_type; | 94 | u8 decryption_type; |
| 95 | u8 frame_status; | 95 | u8 frame_status; |
| @@ -120,14 +120,17 @@ enum mac_flags { | |||
| 120 | MAC_FIXED_CHANNEL = 0x01, | 120 | MAC_FIXED_CHANNEL = 0x01, |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | #define ZD_MAC_STATS_BUFFER_SIZE 16 | ||
| 124 | |||
| 123 | struct zd_mac { | 125 | struct zd_mac { |
| 124 | struct net_device *netdev; | 126 | struct net_device *netdev; |
| 125 | struct zd_chip chip; | 127 | struct zd_chip chip; |
| 126 | spinlock_t lock; | 128 | spinlock_t lock; |
| 127 | /* Unlocked reading possible */ | 129 | /* Unlocked reading possible */ |
| 128 | struct iw_statistics iw_stats; | 130 | struct iw_statistics iw_stats; |
| 129 | u8 qual_average; | 131 | unsigned int stats_count; |
| 130 | u8 rssi_average; | 132 | u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; |
| 133 | u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; | ||
| 131 | u8 regdomain; | 134 | u8 regdomain; |
| 132 | u8 default_regdomain; | 135 | u8 default_regdomain; |
| 133 | u8 requested_channel; | 136 | u8 requested_channel; |
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index 548854754921..1a93fa684e9f 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
| @@ -92,15 +92,6 @@ config QETH_VLAN | |||
| 92 | If CONFIG_QETH is switched on, this option will include IEEE | 92 | If CONFIG_QETH is switched on, this option will include IEEE |
| 93 | 802.1q VLAN support in the qeth device driver. | 93 | 802.1q VLAN support in the qeth device driver. |
| 94 | 94 | ||
| 95 | config QETH_PERF_STATS | ||
| 96 | bool "Performance statistics in /proc" | ||
| 97 | depends on QETH | ||
| 98 | help | ||
| 99 | When switched on, this option will add a file in the proc-fs | ||
| 100 | (/proc/qeth_perf_stats) containing performance statistics. It | ||
| 101 | may slightly impact performance, so this is only recommended for | ||
| 102 | internal tuning of the device driver. | ||
| 103 | |||
| 104 | config CCWGROUP | 95 | config CCWGROUP |
| 105 | tristate | 96 | tristate |
| 106 | default (LCS || CTC || QETH) | 97 | default (LCS || CTC || QETH) |
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 6775a837d646..4777e36a922f 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile | |||
| @@ -10,7 +10,6 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o | |||
| 10 | obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o | 10 | obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o |
| 11 | obj-$(CONFIG_LCS) += lcs.o cu3088.o | 11 | obj-$(CONFIG_LCS) += lcs.o cu3088.o |
| 12 | obj-$(CONFIG_CLAW) += claw.o cu3088.o | 12 | obj-$(CONFIG_CLAW) += claw.o cu3088.o |
| 13 | obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o | ||
| 14 | qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o | 13 | qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o |
| 15 | qeth-$(CONFIG_PROC_FS) += qeth_proc.o | 14 | qeth-$(CONFIG_PROC_FS) += qeth_proc.o |
| 16 | obj-$(CONFIG_QETH) += qeth.o | 15 | obj-$(CONFIG_QETH) += qeth.o |
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 8a4b58120146..3257c22dd79c 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
| @@ -1714,6 +1714,9 @@ add_channel(struct ccw_device *cdev, enum channel_types type) | |||
| 1714 | kfree(ch); | 1714 | kfree(ch); |
| 1715 | return 0; | 1715 | return 0; |
| 1716 | } | 1716 | } |
| 1717 | |||
| 1718 | spin_lock_init(&ch->collect_lock); | ||
| 1719 | |||
| 1717 | fsm_settimer(ch->fsm, &ch->timer); | 1720 | fsm_settimer(ch->fsm, &ch->timer); |
| 1718 | skb_queue_head_init(&ch->io_queue); | 1721 | skb_queue_head_init(&ch->io_queue); |
| 1719 | skb_queue_head_init(&ch->collect_queue); | 1722 | skb_queue_head_init(&ch->collect_queue); |
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index 0e863df4027a..821dde86e240 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c | |||
| @@ -335,8 +335,8 @@ do { \ | |||
| 335 | 335 | ||
| 336 | #else | 336 | #else |
| 337 | 337 | ||
| 338 | #define iucv_debug(lvl, fmt, args...) | 338 | #define iucv_debug(lvl, fmt, args...) do { } while (0) |
| 339 | #define iucv_dumpit(title, buf, len) | 339 | #define iucv_dumpit(title, buf, len) do { } while (0) |
| 340 | 340 | ||
| 341 | #endif | 341 | #endif |
| 342 | 342 | ||
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 2eded55ae88d..16ac68c27a27 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
| @@ -670,9 +670,8 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
| 670 | int index, rc; | 670 | int index, rc; |
| 671 | 671 | ||
| 672 | LCS_DBF_TEXT(5, trace, "rdybuff"); | 672 | LCS_DBF_TEXT(5, trace, "rdybuff"); |
| 673 | if (buffer->state != BUF_STATE_LOCKED && | 673 | BUG_ON(buffer->state != BUF_STATE_LOCKED && |
| 674 | buffer->state != BUF_STATE_PROCESSED) | 674 | buffer->state != BUF_STATE_PROCESSED); |
| 675 | BUG(); | ||
| 676 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 675 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
| 677 | buffer->state = BUF_STATE_READY; | 676 | buffer->state = BUF_STATE_READY; |
| 678 | index = buffer - channel->iob; | 677 | index = buffer - channel->iob; |
| @@ -696,8 +695,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
| 696 | int index, prev, next; | 695 | int index, prev, next; |
| 697 | 696 | ||
| 698 | LCS_DBF_TEXT(5, trace, "prcsbuff"); | 697 | LCS_DBF_TEXT(5, trace, "prcsbuff"); |
| 699 | if (buffer->state != BUF_STATE_READY) | 698 | BUG_ON(buffer->state != BUF_STATE_READY); |
| 700 | BUG(); | ||
| 701 | buffer->state = BUF_STATE_PROCESSED; | 699 | buffer->state = BUF_STATE_PROCESSED; |
| 702 | index = buffer - channel->iob; | 700 | index = buffer - channel->iob; |
| 703 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); | 701 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); |
| @@ -729,9 +727,8 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
| 729 | unsigned long flags; | 727 | unsigned long flags; |
| 730 | 728 | ||
| 731 | LCS_DBF_TEXT(5, trace, "relbuff"); | 729 | LCS_DBF_TEXT(5, trace, "relbuff"); |
| 732 | if (buffer->state != BUF_STATE_LOCKED && | 730 | BUG_ON(buffer->state != BUF_STATE_LOCKED && |
| 733 | buffer->state != BUF_STATE_PROCESSED) | 731 | buffer->state != BUF_STATE_PROCESSED); |
| 734 | BUG(); | ||
| 735 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 732 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
| 736 | buffer->state = BUF_STATE_EMPTY; | 733 | buffer->state = BUF_STATE_EMPTY; |
| 737 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 734 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 5d6e6cbfa360..d7d1cc0a5c8e 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
| @@ -112,7 +112,12 @@ struct iucv_connection { | |||
| 112 | /** | 112 | /** |
| 113 | * Linked list of all connection structs. | 113 | * Linked list of all connection structs. |
| 114 | */ | 114 | */ |
| 115 | static struct iucv_connection *iucv_connections; | 115 | struct iucv_connection_struct { |
| 116 | struct iucv_connection *iucv_connections; | ||
| 117 | rwlock_t iucv_rwlock; | ||
| 118 | }; | ||
| 119 | |||
| 120 | static struct iucv_connection_struct iucv_conns; | ||
| 116 | 121 | ||
| 117 | /** | 122 | /** |
| 118 | * Representation of event-data for the | 123 | * Representation of event-data for the |
| @@ -1368,8 +1373,10 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 1368 | struct net_device *ndev = priv->conn->netdev; | 1373 | struct net_device *ndev = priv->conn->netdev; |
| 1369 | char *p; | 1374 | char *p; |
| 1370 | char *tmp; | 1375 | char *tmp; |
| 1371 | char username[10]; | 1376 | char username[9]; |
| 1372 | int i; | 1377 | int i; |
| 1378 | struct iucv_connection **clist = &iucv_conns.iucv_connections; | ||
| 1379 | unsigned long flags; | ||
| 1373 | 1380 | ||
| 1374 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); | 1381 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); |
| 1375 | if (count>9) { | 1382 | if (count>9) { |
| @@ -1382,7 +1389,7 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 1382 | tmp = strsep((char **) &buf, "\n"); | 1389 | tmp = strsep((char **) &buf, "\n"); |
| 1383 | for (i=0, p=tmp; i<8 && *p; i++, p++) { | 1390 | for (i=0, p=tmp; i<8 && *p; i++, p++) { |
| 1384 | if (isalnum(*p) || (*p == '$')) | 1391 | if (isalnum(*p) || (*p == '$')) |
| 1385 | username[i]= *p; | 1392 | username[i]= toupper(*p); |
| 1386 | else if (*p == '\n') { | 1393 | else if (*p == '\n') { |
| 1387 | /* trailing lf, grr */ | 1394 | /* trailing lf, grr */ |
| 1388 | break; | 1395 | break; |
| @@ -1395,11 +1402,11 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 1395 | return -EINVAL; | 1402 | return -EINVAL; |
| 1396 | } | 1403 | } |
| 1397 | } | 1404 | } |
| 1398 | while (i<9) | 1405 | while (i<8) |
| 1399 | username[i++] = ' '; | 1406 | username[i++] = ' '; |
| 1400 | username[9] = '\0'; | 1407 | username[8] = '\0'; |
| 1401 | 1408 | ||
| 1402 | if (memcmp(username, priv->conn->userid, 8)) { | 1409 | if (memcmp(username, priv->conn->userid, 9)) { |
| 1403 | /* username changed */ | 1410 | /* username changed */ |
| 1404 | if (ndev->flags & (IFF_UP | IFF_RUNNING)) { | 1411 | if (ndev->flags & (IFF_UP | IFF_RUNNING)) { |
| 1405 | PRINT_WARN( | 1412 | PRINT_WARN( |
| @@ -1410,6 +1417,19 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 1410 | return -EBUSY; | 1417 | return -EBUSY; |
| 1411 | } | 1418 | } |
| 1412 | } | 1419 | } |
| 1420 | read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); | ||
| 1421 | while (*clist) { | ||
| 1422 | if (!strncmp(username, (*clist)->userid, 9) || | ||
| 1423 | ((*clist)->netdev != ndev)) | ||
| 1424 | break; | ||
| 1425 | clist = &((*clist)->next); | ||
| 1426 | } | ||
| 1427 | read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 1428 | if (*clist) { | ||
| 1429 | PRINT_WARN("netiucv: Connection to %s already exists\n", | ||
| 1430 | username); | ||
| 1431 | return -EEXIST; | ||
| 1432 | } | ||
| 1413 | memcpy(priv->conn->userid, username, 9); | 1433 | memcpy(priv->conn->userid, username, 9); |
| 1414 | 1434 | ||
| 1415 | return count; | 1435 | return count; |
| @@ -1781,13 +1801,15 @@ netiucv_unregister_device(struct device *dev) | |||
| 1781 | static struct iucv_connection * | 1801 | static struct iucv_connection * |
| 1782 | netiucv_new_connection(struct net_device *dev, char *username) | 1802 | netiucv_new_connection(struct net_device *dev, char *username) |
| 1783 | { | 1803 | { |
| 1784 | struct iucv_connection **clist = &iucv_connections; | 1804 | unsigned long flags; |
| 1805 | struct iucv_connection **clist = &iucv_conns.iucv_connections; | ||
| 1785 | struct iucv_connection *conn = | 1806 | struct iucv_connection *conn = |
| 1786 | kzalloc(sizeof(struct iucv_connection), GFP_KERNEL); | 1807 | kzalloc(sizeof(struct iucv_connection), GFP_KERNEL); |
| 1787 | 1808 | ||
| 1788 | if (conn) { | 1809 | if (conn) { |
| 1789 | skb_queue_head_init(&conn->collect_queue); | 1810 | skb_queue_head_init(&conn->collect_queue); |
| 1790 | skb_queue_head_init(&conn->commit_queue); | 1811 | skb_queue_head_init(&conn->commit_queue); |
| 1812 | spin_lock_init(&conn->collect_lock); | ||
| 1791 | conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; | 1813 | conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; |
| 1792 | conn->netdev = dev; | 1814 | conn->netdev = dev; |
| 1793 | 1815 | ||
| @@ -1822,8 +1844,10 @@ netiucv_new_connection(struct net_device *dev, char *username) | |||
| 1822 | fsm_newstate(conn->fsm, CONN_STATE_STOPPED); | 1844 | fsm_newstate(conn->fsm, CONN_STATE_STOPPED); |
| 1823 | } | 1845 | } |
| 1824 | 1846 | ||
| 1847 | write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); | ||
| 1825 | conn->next = *clist; | 1848 | conn->next = *clist; |
| 1826 | *clist = conn; | 1849 | *clist = conn; |
| 1850 | write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 1827 | } | 1851 | } |
| 1828 | return conn; | 1852 | return conn; |
| 1829 | } | 1853 | } |
| @@ -1835,14 +1859,17 @@ netiucv_new_connection(struct net_device *dev, char *username) | |||
| 1835 | static void | 1859 | static void |
| 1836 | netiucv_remove_connection(struct iucv_connection *conn) | 1860 | netiucv_remove_connection(struct iucv_connection *conn) |
| 1837 | { | 1861 | { |
| 1838 | struct iucv_connection **clist = &iucv_connections; | 1862 | struct iucv_connection **clist = &iucv_conns.iucv_connections; |
| 1863 | unsigned long flags; | ||
| 1839 | 1864 | ||
| 1840 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); | 1865 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); |
| 1841 | if (conn == NULL) | 1866 | if (conn == NULL) |
| 1842 | return; | 1867 | return; |
| 1868 | write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); | ||
| 1843 | while (*clist) { | 1869 | while (*clist) { |
| 1844 | if (*clist == conn) { | 1870 | if (*clist == conn) { |
| 1845 | *clist = conn->next; | 1871 | *clist = conn->next; |
| 1872 | write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 1846 | if (conn->handle) { | 1873 | if (conn->handle) { |
| 1847 | iucv_unregister_program(conn->handle); | 1874 | iucv_unregister_program(conn->handle); |
| 1848 | conn->handle = NULL; | 1875 | conn->handle = NULL; |
| @@ -1855,6 +1882,7 @@ netiucv_remove_connection(struct iucv_connection *conn) | |||
| 1855 | } | 1882 | } |
| 1856 | clist = &((*clist)->next); | 1883 | clist = &((*clist)->next); |
| 1857 | } | 1884 | } |
| 1885 | write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 1858 | } | 1886 | } |
| 1859 | 1887 | ||
| 1860 | /** | 1888 | /** |
| @@ -1947,9 +1975,11 @@ static ssize_t | |||
| 1947 | conn_write(struct device_driver *drv, const char *buf, size_t count) | 1975 | conn_write(struct device_driver *drv, const char *buf, size_t count) |
| 1948 | { | 1976 | { |
| 1949 | char *p; | 1977 | char *p; |
| 1950 | char username[10]; | 1978 | char username[9]; |
| 1951 | int i, ret; | 1979 | int i, ret; |
| 1952 | struct net_device *dev; | 1980 | struct net_device *dev; |
| 1981 | struct iucv_connection **clist = &iucv_conns.iucv_connections; | ||
| 1982 | unsigned long flags; | ||
| 1953 | 1983 | ||
| 1954 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); | 1984 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); |
| 1955 | if (count>9) { | 1985 | if (count>9) { |
| @@ -1960,7 +1990,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) | |||
| 1960 | 1990 | ||
| 1961 | for (i=0, p=(char *)buf; i<8 && *p; i++, p++) { | 1991 | for (i=0, p=(char *)buf; i<8 && *p; i++, p++) { |
| 1962 | if (isalnum(*p) || (*p == '$')) | 1992 | if (isalnum(*p) || (*p == '$')) |
| 1963 | username[i]= *p; | 1993 | username[i]= toupper(*p); |
| 1964 | else if (*p == '\n') { | 1994 | else if (*p == '\n') { |
| 1965 | /* trailing lf, grr */ | 1995 | /* trailing lf, grr */ |
| 1966 | break; | 1996 | break; |
| @@ -1971,9 +2001,22 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) | |||
| 1971 | return -EINVAL; | 2001 | return -EINVAL; |
| 1972 | } | 2002 | } |
| 1973 | } | 2003 | } |
| 1974 | while (i<9) | 2004 | while (i<8) |
| 1975 | username[i++] = ' '; | 2005 | username[i++] = ' '; |
| 1976 | username[9] = '\0'; | 2006 | username[8] = '\0'; |
| 2007 | |||
| 2008 | read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); | ||
| 2009 | while (*clist) { | ||
| 2010 | if (!strncmp(username, (*clist)->userid, 9)) | ||
| 2011 | break; | ||
| 2012 | clist = &((*clist)->next); | ||
| 2013 | } | ||
| 2014 | read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 2015 | if (*clist) { | ||
| 2016 | PRINT_WARN("netiucv: Connection to %s already exists\n", | ||
| 2017 | username); | ||
| 2018 | return -EEXIST; | ||
| 2019 | } | ||
| 1977 | dev = netiucv_init_netdevice(username); | 2020 | dev = netiucv_init_netdevice(username); |
| 1978 | if (!dev) { | 2021 | if (!dev) { |
| 1979 | PRINT_WARN( | 2022 | PRINT_WARN( |
| @@ -2015,7 +2058,8 @@ DRIVER_ATTR(connection, 0200, NULL, conn_write); | |||
| 2015 | static ssize_t | 2058 | static ssize_t |
| 2016 | remove_write (struct device_driver *drv, const char *buf, size_t count) | 2059 | remove_write (struct device_driver *drv, const char *buf, size_t count) |
| 2017 | { | 2060 | { |
| 2018 | struct iucv_connection **clist = &iucv_connections; | 2061 | struct iucv_connection **clist = &iucv_conns.iucv_connections; |
| 2062 | unsigned long flags; | ||
| 2019 | struct net_device *ndev; | 2063 | struct net_device *ndev; |
| 2020 | struct netiucv_priv *priv; | 2064 | struct netiucv_priv *priv; |
| 2021 | struct device *dev; | 2065 | struct device *dev; |
| @@ -2026,7 +2070,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) | |||
| 2026 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); | 2070 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); |
| 2027 | 2071 | ||
| 2028 | if (count >= IFNAMSIZ) | 2072 | if (count >= IFNAMSIZ) |
| 2029 | count = IFNAMSIZ-1; | 2073 | count = IFNAMSIZ - 1;; |
| 2030 | 2074 | ||
| 2031 | for (i=0, p=(char *)buf; i<count && *p; i++, p++) { | 2075 | for (i=0, p=(char *)buf; i<count && *p; i++, p++) { |
| 2032 | if ((*p == '\n') || (*p == ' ')) { | 2076 | if ((*p == '\n') || (*p == ' ')) { |
| @@ -2038,6 +2082,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) | |||
| 2038 | } | 2082 | } |
| 2039 | name[i] = '\0'; | 2083 | name[i] = '\0'; |
| 2040 | 2084 | ||
| 2085 | read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); | ||
| 2041 | while (*clist) { | 2086 | while (*clist) { |
| 2042 | ndev = (*clist)->netdev; | 2087 | ndev = (*clist)->netdev; |
| 2043 | priv = (struct netiucv_priv*)ndev->priv; | 2088 | priv = (struct netiucv_priv*)ndev->priv; |
| @@ -2047,6 +2092,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) | |||
| 2047 | clist = &((*clist)->next); | 2092 | clist = &((*clist)->next); |
| 2048 | continue; | 2093 | continue; |
| 2049 | } | 2094 | } |
| 2095 | read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 2050 | if (ndev->flags & (IFF_UP | IFF_RUNNING)) { | 2096 | if (ndev->flags & (IFF_UP | IFF_RUNNING)) { |
| 2051 | PRINT_WARN( | 2097 | PRINT_WARN( |
| 2052 | "netiucv: net device %s active with peer %s\n", | 2098 | "netiucv: net device %s active with peer %s\n", |
| @@ -2060,6 +2106,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) | |||
| 2060 | netiucv_unregister_device(dev); | 2106 | netiucv_unregister_device(dev); |
| 2061 | return count; | 2107 | return count; |
| 2062 | } | 2108 | } |
| 2109 | read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); | ||
| 2063 | PRINT_WARN("netiucv: net device %s unknown\n", name); | 2110 | PRINT_WARN("netiucv: net device %s unknown\n", name); |
| 2064 | IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n"); | 2111 | IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n"); |
| 2065 | return -EINVAL; | 2112 | return -EINVAL; |
| @@ -2077,8 +2124,8 @@ static void __exit | |||
| 2077 | netiucv_exit(void) | 2124 | netiucv_exit(void) |
| 2078 | { | 2125 | { |
| 2079 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); | 2126 | IUCV_DBF_TEXT(trace, 3, __FUNCTION__); |
| 2080 | while (iucv_connections) { | 2127 | while (iucv_conns.iucv_connections) { |
| 2081 | struct net_device *ndev = iucv_connections->netdev; | 2128 | struct net_device *ndev = iucv_conns.iucv_connections->netdev; |
| 2082 | struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; | 2129 | struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; |
| 2083 | struct device *dev = priv->dev; | 2130 | struct device *dev = priv->dev; |
| 2084 | 2131 | ||
| @@ -2120,6 +2167,7 @@ netiucv_init(void) | |||
| 2120 | if (!ret) { | 2167 | if (!ret) { |
| 2121 | ret = driver_create_file(&netiucv_driver, &driver_attr_remove); | 2168 | ret = driver_create_file(&netiucv_driver, &driver_attr_remove); |
| 2122 | netiucv_banner(); | 2169 | netiucv_banner(); |
| 2170 | rwlock_init(&iucv_conns.iucv_rwlock); | ||
| 2123 | } else { | 2171 | } else { |
| 2124 | PRINT_ERR("NETIUCV: failed to add driver attribute.\n"); | 2172 | PRINT_ERR("NETIUCV: failed to add driver attribute.\n"); |
| 2125 | IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret); | 2173 | IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret); |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 619f4a0c7160..821383d8cbe7 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
| @@ -176,7 +176,6 @@ extern struct ccwgroup_driver qeth_ccwgroup_driver; | |||
| 176 | /** | 176 | /** |
| 177 | * card stuff | 177 | * card stuff |
| 178 | */ | 178 | */ |
| 179 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 180 | struct qeth_perf_stats { | 179 | struct qeth_perf_stats { |
| 181 | unsigned int bufs_rec; | 180 | unsigned int bufs_rec; |
| 182 | unsigned int bufs_sent; | 181 | unsigned int bufs_sent; |
| @@ -211,8 +210,10 @@ struct qeth_perf_stats { | |||
| 211 | unsigned int large_send_cnt; | 210 | unsigned int large_send_cnt; |
| 212 | unsigned int sg_skbs_sent; | 211 | unsigned int sg_skbs_sent; |
| 213 | unsigned int sg_frags_sent; | 212 | unsigned int sg_frags_sent; |
| 213 | /* initial values when measuring starts */ | ||
| 214 | unsigned long initial_rx_packets; | ||
| 215 | unsigned long initial_tx_packets; | ||
| 214 | }; | 216 | }; |
| 215 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
| 216 | 217 | ||
| 217 | /* Routing stuff */ | 218 | /* Routing stuff */ |
| 218 | struct qeth_routing_info { | 219 | struct qeth_routing_info { |
| @@ -462,6 +463,7 @@ enum qeth_qdio_info_states { | |||
| 462 | QETH_QDIO_UNINITIALIZED, | 463 | QETH_QDIO_UNINITIALIZED, |
| 463 | QETH_QDIO_ALLOCATED, | 464 | QETH_QDIO_ALLOCATED, |
| 464 | QETH_QDIO_ESTABLISHED, | 465 | QETH_QDIO_ESTABLISHED, |
| 466 | QETH_QDIO_CLEANING | ||
| 465 | }; | 467 | }; |
| 466 | 468 | ||
| 467 | struct qeth_buffer_pool_entry { | 469 | struct qeth_buffer_pool_entry { |
| @@ -536,7 +538,7 @@ struct qeth_qdio_out_q { | |||
| 536 | } __attribute__ ((aligned(256))); | 538 | } __attribute__ ((aligned(256))); |
| 537 | 539 | ||
| 538 | struct qeth_qdio_info { | 540 | struct qeth_qdio_info { |
| 539 | volatile enum qeth_qdio_info_states state; | 541 | atomic_t state; |
| 540 | /* input */ | 542 | /* input */ |
| 541 | struct qeth_qdio_q *in_q; | 543 | struct qeth_qdio_q *in_q; |
| 542 | struct qeth_qdio_buffer_pool in_buf_pool; | 544 | struct qeth_qdio_buffer_pool in_buf_pool; |
| @@ -767,6 +769,7 @@ struct qeth_card_options { | |||
| 767 | int fake_ll; | 769 | int fake_ll; |
| 768 | int layer2; | 770 | int layer2; |
| 769 | enum qeth_large_send_types large_send; | 771 | enum qeth_large_send_types large_send; |
| 772 | int performance_stats; | ||
| 770 | }; | 773 | }; |
| 771 | 774 | ||
| 772 | /* | 775 | /* |
| @@ -819,9 +822,7 @@ struct qeth_card { | |||
| 819 | struct list_head cmd_waiter_list; | 822 | struct list_head cmd_waiter_list; |
| 820 | /* QDIO buffer handling */ | 823 | /* QDIO buffer handling */ |
| 821 | struct qeth_qdio_info qdio; | 824 | struct qeth_qdio_info qdio; |
| 822 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 823 | struct qeth_perf_stats perf_stats; | 825 | struct qeth_perf_stats perf_stats; |
| 824 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
| 825 | int use_hard_stop; | 826 | int use_hard_stop; |
| 826 | int (*orig_hard_header)(struct sk_buff *,struct net_device *, | 827 | int (*orig_hard_header)(struct sk_buff *,struct net_device *, |
| 827 | unsigned short,void *,void *,unsigned); | 828 | unsigned short,void *,void *,unsigned); |
| @@ -859,23 +860,18 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type) | |||
| 859 | } | 860 | } |
| 860 | } | 861 | } |
| 861 | 862 | ||
| 862 | static inline int | 863 | static inline struct sk_buff * |
| 863 | qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size) | 864 | qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size) |
| 864 | { | 865 | { |
| 865 | struct sk_buff *new_skb = NULL; | 866 | struct sk_buff *new_skb = skb; |
| 866 | 867 | ||
| 867 | if (skb_headroom(*skb) < size){ | 868 | if (skb_headroom(skb) >= size) |
| 868 | new_skb = skb_realloc_headroom(*skb, size); | 869 | return skb; |
| 869 | if (!new_skb) { | 870 | new_skb = skb_realloc_headroom(skb, size); |
| 870 | PRINT_ERR("qeth_prepare_skb: could " | 871 | if (!new_skb) |
| 871 | "not realloc headroom for qeth_hdr " | 872 | PRINT_ERR("Could not realloc headroom for qeth_hdr " |
| 872 | "on interface %s", QETH_CARD_IFNAME(card)); | 873 | "on interface %s", QETH_CARD_IFNAME(card)); |
| 873 | return -ENOMEM; | 874 | return new_skb; |
| 874 | } | ||
| 875 | kfree_skb(*skb); | ||
| 876 | *skb = new_skb; | ||
| 877 | } | ||
| 878 | return 0; | ||
| 879 | } | 875 | } |
| 880 | 876 | ||
| 881 | static inline struct sk_buff * | 877 | static inline struct sk_buff * |
| @@ -885,16 +881,15 @@ qeth_pskb_unshare(struct sk_buff *skb, int pri) | |||
| 885 | if (!skb_cloned(skb)) | 881 | if (!skb_cloned(skb)) |
| 886 | return skb; | 882 | return skb; |
| 887 | nskb = skb_copy(skb, pri); | 883 | nskb = skb_copy(skb, pri); |
| 888 | kfree_skb(skb); /* free our shared copy */ | ||
| 889 | return nskb; | 884 | return nskb; |
| 890 | } | 885 | } |
| 891 | 886 | ||
| 892 | static inline void * | 887 | static inline void * |
| 893 | qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) | 888 | qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size) |
| 894 | { | 889 | { |
| 895 | void *hdr; | 890 | void *hdr; |
| 896 | 891 | ||
| 897 | hdr = (void *) skb_push(*skb, size); | 892 | hdr = (void *) skb_push(skb, size); |
| 898 | /* | 893 | /* |
| 899 | * sanity check, the Linux memory allocation scheme should | 894 | * sanity check, the Linux memory allocation scheme should |
| 900 | * never present us cases like this one (the qdio header size plus | 895 | * never present us cases like this one (the qdio header size plus |
| @@ -903,8 +898,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) | |||
| 903 | if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) != | 898 | if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) != |
| 904 | (((unsigned long) hdr + size + | 899 | (((unsigned long) hdr + size + |
| 905 | QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { | 900 | QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { |
| 906 | PRINT_ERR("qeth_prepare_skb: misaligned " | 901 | PRINT_ERR("Misaligned packet on interface %s. Discarded.", |
| 907 | "packet on interface %s. Discarded.", | ||
| 908 | QETH_CARD_IFNAME(card)); | 902 | QETH_CARD_IFNAME(card)); |
| 909 | return NULL; | 903 | return NULL; |
| 910 | } | 904 | } |
| @@ -1056,13 +1050,11 @@ qeth_get_arphdr_type(int cardtype, int linktype) | |||
| 1056 | } | 1050 | } |
| 1057 | } | 1051 | } |
| 1058 | 1052 | ||
| 1059 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 1060 | static inline int | 1053 | static inline int |
| 1061 | qeth_get_micros(void) | 1054 | qeth_get_micros(void) |
| 1062 | { | 1055 | { |
| 1063 | return (int) (get_clock() >> 12); | 1056 | return (int) (get_clock() >> 12); |
| 1064 | } | 1057 | } |
| 1065 | #endif | ||
| 1066 | 1058 | ||
| 1067 | static inline int | 1059 | static inline int |
| 1068 | qeth_get_qdio_q_format(struct qeth_card *card) | 1060 | qeth_get_qdio_q_format(struct qeth_card *card) |
| @@ -1096,10 +1088,11 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) | |||
| 1096 | { | 1088 | { |
| 1097 | int count = 0, rc = 0; | 1089 | int count = 0, rc = 0; |
| 1098 | int in[4]; | 1090 | int in[4]; |
| 1091 | char c; | ||
| 1099 | 1092 | ||
| 1100 | rc = sscanf(buf, "%d.%d.%d.%d%n", | 1093 | rc = sscanf(buf, "%u.%u.%u.%u%c", |
| 1101 | &in[0], &in[1], &in[2], &in[3], &count); | 1094 | &in[0], &in[1], &in[2], &in[3], &c); |
| 1102 | if (rc != 4 || count<=0) | 1095 | if (rc != 4 && (rc != 5 || c != '\n')) |
| 1103 | return -EINVAL; | 1096 | return -EINVAL; |
| 1104 | for (count = 0; count < 4; count++) { | 1097 | for (count = 0; count < 4; count++) { |
| 1105 | if (in[count] > 255) | 1098 | if (in[count] > 255) |
| @@ -1123,24 +1116,28 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf) | |||
| 1123 | static inline int | 1116 | static inline int |
| 1124 | qeth_string_to_ipaddr6(const char *buf, __u8 *addr) | 1117 | qeth_string_to_ipaddr6(const char *buf, __u8 *addr) |
| 1125 | { | 1118 | { |
| 1126 | char *end, *start; | 1119 | const char *end, *end_tmp, *start; |
| 1127 | __u16 *in; | 1120 | __u16 *in; |
| 1128 | char num[5]; | 1121 | char num[5]; |
| 1129 | int num2, cnt, out, found, save_cnt; | 1122 | int num2, cnt, out, found, save_cnt; |
| 1130 | unsigned short in_tmp[8] = {0, }; | 1123 | unsigned short in_tmp[8] = {0, }; |
| 1131 | 1124 | ||
| 1132 | cnt = out = found = save_cnt = num2 = 0; | 1125 | cnt = out = found = save_cnt = num2 = 0; |
| 1133 | end = start = (char *) buf; | 1126 | end = start = buf; |
| 1134 | in = (__u16 *) addr; | 1127 | in = (__u16 *) addr; |
| 1135 | memset(in, 0, 16); | 1128 | memset(in, 0, 16); |
| 1136 | while (end) { | 1129 | while (*end) { |
| 1137 | end = strchr(end,':'); | 1130 | end = strchr(start,':'); |
| 1138 | if (end == NULL) { | 1131 | if (end == NULL) { |
| 1139 | end = (char *)buf + (strlen(buf)); | 1132 | end = buf + strlen(buf); |
| 1140 | out = 1; | 1133 | if ((end_tmp = strchr(start, '\n')) != NULL) |
| 1134 | end = end_tmp; | ||
| 1135 | out = 1; | ||
| 1141 | } | 1136 | } |
| 1142 | if ((end - start)) { | 1137 | if ((end - start)) { |
| 1143 | memset(num, 0, 5); | 1138 | memset(num, 0, 5); |
| 1139 | if ((end - start) > 4) | ||
| 1140 | return -EINVAL; | ||
| 1144 | memcpy(num, start, end - start); | 1141 | memcpy(num, start, end - start); |
| 1145 | if (!qeth_isxdigit(num)) | 1142 | if (!qeth_isxdigit(num)) |
| 1146 | return -EINVAL; | 1143 | return -EINVAL; |
| @@ -1158,6 +1155,8 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) | |||
| 1158 | } | 1155 | } |
| 1159 | start = ++end; | 1156 | start = ++end; |
| 1160 | } | 1157 | } |
| 1158 | if (cnt + save_cnt > 8) | ||
| 1159 | return -EINVAL; | ||
| 1161 | cnt = 7; | 1160 | cnt = 7; |
| 1162 | while (save_cnt) | 1161 | while (save_cnt) |
| 1163 | in[cnt--] = in_tmp[--save_cnt]; | 1162 | in[cnt--] = in_tmp[--save_cnt]; |
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 8491598f9149..a363721cf28d 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
| @@ -179,9 +179,8 @@ out_check: | |||
| 179 | flush_cnt++; | 179 | flush_cnt++; |
| 180 | } | 180 | } |
| 181 | } else { | 181 | } else { |
| 182 | #ifdef CONFIG_QETH_PERF_STATS | 182 | if (queue->card->options.performance_stats) |
| 183 | queue->card->perf_stats.skbs_sent_pack++; | 183 | queue->card->perf_stats.skbs_sent_pack++; |
| 184 | #endif | ||
| 185 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); | 184 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); |
| 186 | if (buf->next_element_to_fill >= | 185 | if (buf->next_element_to_fill >= |
| 187 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { | 186 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index e1327b8fce00..5613b4564fa2 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
| @@ -1073,6 +1073,7 @@ qeth_set_intial_options(struct qeth_card *card) | |||
| 1073 | card->options.layer2 = 1; | 1073 | card->options.layer2 = 1; |
| 1074 | else | 1074 | else |
| 1075 | card->options.layer2 = 0; | 1075 | card->options.layer2 = 0; |
| 1076 | card->options.performance_stats = 1; | ||
| 1076 | } | 1077 | } |
| 1077 | 1078 | ||
| 1078 | /** | 1079 | /** |
| @@ -1708,6 +1709,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | |||
| 1708 | "IP address reset.\n", | 1709 | "IP address reset.\n", |
| 1709 | QETH_CARD_IFNAME(card), | 1710 | QETH_CARD_IFNAME(card), |
| 1710 | card->info.chpid); | 1711 | card->info.chpid); |
| 1712 | netif_carrier_on(card->dev); | ||
| 1711 | qeth_schedule_recovery(card); | 1713 | qeth_schedule_recovery(card); |
| 1712 | return NULL; | 1714 | return NULL; |
| 1713 | case IPA_CMD_MODCCID: | 1715 | case IPA_CMD_MODCCID: |
| @@ -2464,24 +2466,6 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, | |||
| 2464 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); | 2466 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); |
| 2465 | } | 2467 | } |
| 2466 | 2468 | ||
| 2467 | static inline void | ||
| 2468 | qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, | ||
| 2469 | struct qeth_hdr *hdr) | ||
| 2470 | { | ||
| 2471 | #ifdef CONFIG_QETH_VLAN | ||
| 2472 | u16 *vlan_tag; | ||
| 2473 | |||
| 2474 | if (hdr->hdr.l3.ext_flags & | ||
| 2475 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | ||
| 2476 | vlan_tag = (u16 *) skb_push(skb, VLAN_HLEN); | ||
| 2477 | *vlan_tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | ||
| 2478 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | ||
| 2479 | *(vlan_tag + 1) = skb->protocol; | ||
| 2480 | skb->protocol = __constant_htons(ETH_P_8021Q); | ||
| 2481 | } | ||
| 2482 | #endif /* CONFIG_QETH_VLAN */ | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | static inline __u16 | 2469 | static inline __u16 |
| 2486 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2470 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
| 2487 | struct qeth_hdr *hdr) | 2471 | struct qeth_hdr *hdr) |
| @@ -2510,15 +2494,16 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
| 2510 | return vlan_id; | 2494 | return vlan_id; |
| 2511 | } | 2495 | } |
| 2512 | 2496 | ||
| 2513 | static inline void | 2497 | static inline __u16 |
| 2514 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2498 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
| 2515 | struct qeth_hdr *hdr) | 2499 | struct qeth_hdr *hdr) |
| 2516 | { | 2500 | { |
| 2501 | unsigned short vlan_id = 0; | ||
| 2517 | #ifdef CONFIG_QETH_IPV6 | 2502 | #ifdef CONFIG_QETH_IPV6 |
| 2518 | if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { | 2503 | if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { |
| 2519 | skb->pkt_type = PACKET_HOST; | 2504 | skb->pkt_type = PACKET_HOST; |
| 2520 | skb->protocol = qeth_type_trans(skb, card->dev); | 2505 | skb->protocol = qeth_type_trans(skb, card->dev); |
| 2521 | return; | 2506 | return 0; |
| 2522 | } | 2507 | } |
| 2523 | #endif /* CONFIG_QETH_IPV6 */ | 2508 | #endif /* CONFIG_QETH_IPV6 */ |
| 2524 | skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : | 2509 | skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : |
| @@ -2540,7 +2525,13 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
| 2540 | default: | 2525 | default: |
| 2541 | skb->pkt_type = PACKET_HOST; | 2526 | skb->pkt_type = PACKET_HOST; |
| 2542 | } | 2527 | } |
| 2543 | qeth_rebuild_skb_vlan(card, skb, hdr); | 2528 | |
| 2529 | if (hdr->hdr.l3.ext_flags & | ||
| 2530 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | ||
| 2531 | vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | ||
| 2532 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | ||
| 2533 | } | ||
| 2534 | |||
| 2544 | if (card->options.fake_ll) | 2535 | if (card->options.fake_ll) |
| 2545 | qeth_rebuild_skb_fake_ll(card, skb, hdr); | 2536 | qeth_rebuild_skb_fake_ll(card, skb, hdr); |
| 2546 | else | 2537 | else |
| @@ -2556,6 +2547,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
| 2556 | else | 2547 | else |
| 2557 | skb->ip_summed = SW_CHECKSUMMING; | 2548 | skb->ip_summed = SW_CHECKSUMMING; |
| 2558 | } | 2549 | } |
| 2550 | return vlan_id; | ||
| 2559 | } | 2551 | } |
| 2560 | 2552 | ||
| 2561 | static inline void | 2553 | static inline void |
| @@ -2568,20 +2560,20 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
| 2568 | int offset; | 2560 | int offset; |
| 2569 | int rxrc; | 2561 | int rxrc; |
| 2570 | __u16 vlan_tag = 0; | 2562 | __u16 vlan_tag = 0; |
| 2563 | __u16 *vlan_addr; | ||
| 2571 | 2564 | ||
| 2572 | /* get first element of current buffer */ | 2565 | /* get first element of current buffer */ |
| 2573 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 2566 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; |
| 2574 | offset = 0; | 2567 | offset = 0; |
| 2575 | #ifdef CONFIG_QETH_PERF_STATS | 2568 | if (card->options.performance_stats) |
| 2576 | card->perf_stats.bufs_rec++; | 2569 | card->perf_stats.bufs_rec++; |
| 2577 | #endif | ||
| 2578 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, | 2570 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, |
| 2579 | &offset, &hdr))) { | 2571 | &offset, &hdr))) { |
| 2580 | skb->dev = card->dev; | 2572 | skb->dev = card->dev; |
| 2581 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) | 2573 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) |
| 2582 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); | 2574 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); |
| 2583 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) | 2575 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) |
| 2584 | qeth_rebuild_skb(card, skb, hdr); | 2576 | vlan_tag = qeth_rebuild_skb(card, skb, hdr); |
| 2585 | else { /*in case of OSN*/ | 2577 | else { /*in case of OSN*/ |
| 2586 | skb_push(skb, sizeof(struct qeth_hdr)); | 2578 | skb_push(skb, sizeof(struct qeth_hdr)); |
| 2587 | memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); | 2579 | memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); |
| @@ -2591,14 +2583,19 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
| 2591 | dev_kfree_skb_any(skb); | 2583 | dev_kfree_skb_any(skb); |
| 2592 | continue; | 2584 | continue; |
| 2593 | } | 2585 | } |
| 2586 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
| 2587 | rxrc = card->osn_info.data_cb(skb); | ||
| 2588 | else | ||
| 2594 | #ifdef CONFIG_QETH_VLAN | 2589 | #ifdef CONFIG_QETH_VLAN |
| 2595 | if (vlan_tag) | 2590 | if (vlan_tag) |
| 2596 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); | 2591 | if (card->vlangrp) |
| 2592 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); | ||
| 2593 | else { | ||
| 2594 | dev_kfree_skb_any(skb); | ||
| 2595 | continue; | ||
| 2596 | } | ||
| 2597 | else | 2597 | else |
| 2598 | #endif | 2598 | #endif |
| 2599 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
| 2600 | rxrc = card->osn_info.data_cb(skb); | ||
| 2601 | else | ||
| 2602 | rxrc = netif_rx(skb); | 2599 | rxrc = netif_rx(skb); |
| 2603 | card->dev->last_rx = jiffies; | 2600 | card->dev->last_rx = jiffies; |
| 2604 | card->stats.rx_packets++; | 2601 | card->stats.rx_packets++; |
| @@ -2626,7 +2623,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) | |||
| 2626 | { | 2623 | { |
| 2627 | struct qeth_buffer_pool_entry *pool_entry; | 2624 | struct qeth_buffer_pool_entry *pool_entry; |
| 2628 | int i; | 2625 | int i; |
| 2629 | 2626 | ||
| 2630 | pool_entry = qeth_get_buffer_pool_entry(card); | 2627 | pool_entry = qeth_get_buffer_pool_entry(card); |
| 2631 | /* | 2628 | /* |
| 2632 | * since the buffer is accessed only from the input_tasklet | 2629 | * since the buffer is accessed only from the input_tasklet |
| @@ -2700,17 +2697,18 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
| 2700 | * 'index') un-requeued -> this buffer is the first buffer that | 2697 | * 'index') un-requeued -> this buffer is the first buffer that |
| 2701 | * will be requeued the next time | 2698 | * will be requeued the next time |
| 2702 | */ | 2699 | */ |
| 2703 | #ifdef CONFIG_QETH_PERF_STATS | 2700 | if (card->options.performance_stats) { |
| 2704 | card->perf_stats.inbound_do_qdio_cnt++; | 2701 | card->perf_stats.inbound_do_qdio_cnt++; |
| 2705 | card->perf_stats.inbound_do_qdio_start_time = qeth_get_micros(); | 2702 | card->perf_stats.inbound_do_qdio_start_time = |
| 2706 | #endif | 2703 | qeth_get_micros(); |
| 2704 | } | ||
| 2707 | rc = do_QDIO(CARD_DDEV(card), | 2705 | rc = do_QDIO(CARD_DDEV(card), |
| 2708 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2706 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, |
| 2709 | 0, queue->next_buf_to_init, count, NULL); | 2707 | 0, queue->next_buf_to_init, count, NULL); |
| 2710 | #ifdef CONFIG_QETH_PERF_STATS | 2708 | if (card->options.performance_stats) |
| 2711 | card->perf_stats.inbound_do_qdio_time += qeth_get_micros() - | 2709 | card->perf_stats.inbound_do_qdio_time += |
| 2712 | card->perf_stats.inbound_do_qdio_start_time; | 2710 | qeth_get_micros() - |
| 2713 | #endif | 2711 | card->perf_stats.inbound_do_qdio_start_time; |
| 2714 | if (rc){ | 2712 | if (rc){ |
| 2715 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " | 2713 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " |
| 2716 | "return %i (device %s).\n", | 2714 | "return %i (device %s).\n", |
| @@ -2746,10 +2744,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
| 2746 | QETH_DBF_TEXT(trace, 6, "qdinput"); | 2744 | QETH_DBF_TEXT(trace, 6, "qdinput"); |
| 2747 | card = (struct qeth_card *) card_ptr; | 2745 | card = (struct qeth_card *) card_ptr; |
| 2748 | net_dev = card->dev; | 2746 | net_dev = card->dev; |
| 2749 | #ifdef CONFIG_QETH_PERF_STATS | 2747 | if (card->options.performance_stats) { |
| 2750 | card->perf_stats.inbound_cnt++; | 2748 | card->perf_stats.inbound_cnt++; |
| 2751 | card->perf_stats.inbound_start_time = qeth_get_micros(); | 2749 | card->perf_stats.inbound_start_time = qeth_get_micros(); |
| 2752 | #endif | 2750 | } |
| 2753 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { | 2751 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { |
| 2754 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ | 2752 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ |
| 2755 | QETH_DBF_TEXT(trace, 1,"qdinchk"); | 2753 | QETH_DBF_TEXT(trace, 1,"qdinchk"); |
| @@ -2771,10 +2769,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
| 2771 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | 2769 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); |
| 2772 | qeth_queue_input_buffer(card, index); | 2770 | qeth_queue_input_buffer(card, index); |
| 2773 | } | 2771 | } |
| 2774 | #ifdef CONFIG_QETH_PERF_STATS | 2772 | if (card->options.performance_stats) |
| 2775 | card->perf_stats.inbound_time += qeth_get_micros() - | 2773 | card->perf_stats.inbound_time += qeth_get_micros() - |
| 2776 | card->perf_stats.inbound_start_time; | 2774 | card->perf_stats.inbound_start_time; |
| 2777 | #endif | ||
| 2778 | } | 2775 | } |
| 2779 | 2776 | ||
| 2780 | static inline int | 2777 | static inline int |
| @@ -2864,10 +2861,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
| 2864 | } | 2861 | } |
| 2865 | 2862 | ||
| 2866 | queue->card->dev->trans_start = jiffies; | 2863 | queue->card->dev->trans_start = jiffies; |
| 2867 | #ifdef CONFIG_QETH_PERF_STATS | 2864 | if (queue->card->options.performance_stats) { |
| 2868 | queue->card->perf_stats.outbound_do_qdio_cnt++; | 2865 | queue->card->perf_stats.outbound_do_qdio_cnt++; |
| 2869 | queue->card->perf_stats.outbound_do_qdio_start_time = qeth_get_micros(); | 2866 | queue->card->perf_stats.outbound_do_qdio_start_time = |
| 2870 | #endif | 2867 | qeth_get_micros(); |
| 2868 | } | ||
| 2871 | if (under_int) | 2869 | if (under_int) |
| 2872 | rc = do_QDIO(CARD_DDEV(queue->card), | 2870 | rc = do_QDIO(CARD_DDEV(queue->card), |
| 2873 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2871 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, |
| @@ -2875,10 +2873,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
| 2875 | else | 2873 | else |
| 2876 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, | 2874 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, |
| 2877 | queue->queue_no, index, count, NULL); | 2875 | queue->queue_no, index, count, NULL); |
| 2878 | #ifdef CONFIG_QETH_PERF_STATS | 2876 | if (queue->card->options.performance_stats) |
| 2879 | queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - | 2877 | queue->card->perf_stats.outbound_do_qdio_time += |
| 2880 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2878 | qeth_get_micros() - |
| 2881 | #endif | 2879 | queue->card->perf_stats.outbound_do_qdio_start_time; |
| 2882 | if (rc){ | 2880 | if (rc){ |
| 2883 | QETH_DBF_TEXT(trace, 2, "flushbuf"); | 2881 | QETH_DBF_TEXT(trace, 2, "flushbuf"); |
| 2884 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | 2882 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); |
| @@ -2890,9 +2888,8 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
| 2890 | return; | 2888 | return; |
| 2891 | } | 2889 | } |
| 2892 | atomic_add(count, &queue->used_buffers); | 2890 | atomic_add(count, &queue->used_buffers); |
| 2893 | #ifdef CONFIG_QETH_PERF_STATS | 2891 | if (queue->card->options.performance_stats) |
| 2894 | queue->card->perf_stats.bufs_sent += count; | 2892 | queue->card->perf_stats.bufs_sent += count; |
| 2895 | #endif | ||
| 2896 | } | 2893 | } |
| 2897 | 2894 | ||
| 2898 | /* | 2895 | /* |
| @@ -2907,9 +2904,8 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) | |||
| 2907 | >= QETH_HIGH_WATERMARK_PACK){ | 2904 | >= QETH_HIGH_WATERMARK_PACK){ |
| 2908 | /* switch non-PACKING -> PACKING */ | 2905 | /* switch non-PACKING -> PACKING */ |
| 2909 | QETH_DBF_TEXT(trace, 6, "np->pack"); | 2906 | QETH_DBF_TEXT(trace, 6, "np->pack"); |
| 2910 | #ifdef CONFIG_QETH_PERF_STATS | 2907 | if (queue->card->options.performance_stats) |
| 2911 | queue->card->perf_stats.sc_dp_p++; | 2908 | queue->card->perf_stats.sc_dp_p++; |
| 2912 | #endif | ||
| 2913 | queue->do_pack = 1; | 2909 | queue->do_pack = 1; |
| 2914 | } | 2910 | } |
| 2915 | } | 2911 | } |
| @@ -2932,9 +2928,8 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
| 2932 | <= QETH_LOW_WATERMARK_PACK) { | 2928 | <= QETH_LOW_WATERMARK_PACK) { |
| 2933 | /* switch PACKING -> non-PACKING */ | 2929 | /* switch PACKING -> non-PACKING */ |
| 2934 | QETH_DBF_TEXT(trace, 6, "pack->np"); | 2930 | QETH_DBF_TEXT(trace, 6, "pack->np"); |
| 2935 | #ifdef CONFIG_QETH_PERF_STATS | 2931 | if (queue->card->options.performance_stats) |
| 2936 | queue->card->perf_stats.sc_p_dp++; | 2932 | queue->card->perf_stats.sc_p_dp++; |
| 2937 | #endif | ||
| 2938 | queue->do_pack = 0; | 2933 | queue->do_pack = 0; |
| 2939 | /* flush packing buffers */ | 2934 | /* flush packing buffers */ |
| 2940 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 2935 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
| @@ -2946,7 +2941,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
| 2946 | queue->next_buf_to_fill = | 2941 | queue->next_buf_to_fill = |
| 2947 | (queue->next_buf_to_fill + 1) % | 2942 | (queue->next_buf_to_fill + 1) % |
| 2948 | QDIO_MAX_BUFFERS_PER_Q; | 2943 | QDIO_MAX_BUFFERS_PER_Q; |
| 2949 | } | 2944 | } |
| 2950 | } | 2945 | } |
| 2951 | } | 2946 | } |
| 2952 | return flush_count; | 2947 | return flush_count; |
| @@ -3002,11 +2997,10 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
| 3002 | !atomic_read(&queue->set_pci_flags_count)) | 2997 | !atomic_read(&queue->set_pci_flags_count)) |
| 3003 | flush_cnt += | 2998 | flush_cnt += |
| 3004 | qeth_flush_buffers_on_no_pci(queue); | 2999 | qeth_flush_buffers_on_no_pci(queue); |
| 3005 | #ifdef CONFIG_QETH_PERF_STATS | 3000 | if (queue->card->options.performance_stats && |
| 3006 | if (q_was_packing) | 3001 | q_was_packing) |
| 3007 | queue->card->perf_stats.bufs_sent_pack += | 3002 | queue->card->perf_stats.bufs_sent_pack += |
| 3008 | flush_cnt; | 3003 | flush_cnt; |
| 3009 | #endif | ||
| 3010 | if (flush_cnt) | 3004 | if (flush_cnt) |
| 3011 | qeth_flush_buffers(queue, 1, index, flush_cnt); | 3005 | qeth_flush_buffers(queue, 1, index, flush_cnt); |
| 3012 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 3006 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
| @@ -3036,10 +3030,11 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
| 3036 | return; | 3030 | return; |
| 3037 | } | 3031 | } |
| 3038 | } | 3032 | } |
| 3039 | #ifdef CONFIG_QETH_PERF_STATS | 3033 | if (card->options.performance_stats) { |
| 3040 | card->perf_stats.outbound_handler_cnt++; | 3034 | card->perf_stats.outbound_handler_cnt++; |
| 3041 | card->perf_stats.outbound_handler_start_time = qeth_get_micros(); | 3035 | card->perf_stats.outbound_handler_start_time = |
| 3042 | #endif | 3036 | qeth_get_micros(); |
| 3037 | } | ||
| 3043 | for(i = first_element; i < (first_element + count); ++i){ | 3038 | for(i = first_element; i < (first_element + count); ++i){ |
| 3044 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3039 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
| 3045 | /*we only handle the KICK_IT error by doing a recovery */ | 3040 | /*we only handle the KICK_IT error by doing a recovery */ |
| @@ -3058,10 +3053,9 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
| 3058 | qeth_check_outbound_queue(queue); | 3053 | qeth_check_outbound_queue(queue); |
| 3059 | 3054 | ||
| 3060 | netif_wake_queue(queue->card->dev); | 3055 | netif_wake_queue(queue->card->dev); |
| 3061 | #ifdef CONFIG_QETH_PERF_STATS | 3056 | if (card->options.performance_stats) |
| 3062 | card->perf_stats.outbound_handler_time += qeth_get_micros() - | 3057 | card->perf_stats.outbound_handler_time += qeth_get_micros() - |
| 3063 | card->perf_stats.outbound_handler_start_time; | 3058 | card->perf_stats.outbound_handler_start_time; |
| 3064 | #endif | ||
| 3065 | } | 3059 | } |
| 3066 | 3060 | ||
| 3067 | static void | 3061 | static void |
| @@ -3185,13 +3179,14 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
| 3185 | 3179 | ||
| 3186 | QETH_DBF_TEXT(setup, 2, "allcqdbf"); | 3180 | QETH_DBF_TEXT(setup, 2, "allcqdbf"); |
| 3187 | 3181 | ||
| 3188 | if (card->qdio.state == QETH_QDIO_ALLOCATED) | 3182 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED, |
| 3183 | QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) | ||
| 3189 | return 0; | 3184 | return 0; |
| 3190 | 3185 | ||
| 3191 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), | 3186 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), |
| 3192 | GFP_KERNEL|GFP_DMA); | 3187 | GFP_KERNEL|GFP_DMA); |
| 3193 | if (!card->qdio.in_q) | 3188 | if (!card->qdio.in_q) |
| 3194 | return - ENOMEM; | 3189 | goto out_nomem; |
| 3195 | QETH_DBF_TEXT(setup, 2, "inq"); | 3190 | QETH_DBF_TEXT(setup, 2, "inq"); |
| 3196 | QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *)); | 3191 | QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *)); |
| 3197 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); | 3192 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); |
| @@ -3200,27 +3195,19 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
| 3200 | card->qdio.in_q->bufs[i].buffer = | 3195 | card->qdio.in_q->bufs[i].buffer = |
| 3201 | &card->qdio.in_q->qdio_bufs[i]; | 3196 | &card->qdio.in_q->qdio_bufs[i]; |
| 3202 | /* inbound buffer pool */ | 3197 | /* inbound buffer pool */ |
| 3203 | if (qeth_alloc_buffer_pool(card)){ | 3198 | if (qeth_alloc_buffer_pool(card)) |
| 3204 | kfree(card->qdio.in_q); | 3199 | goto out_freeinq; |
| 3205 | return -ENOMEM; | ||
| 3206 | } | ||
| 3207 | /* outbound */ | 3200 | /* outbound */ |
| 3208 | card->qdio.out_qs = | 3201 | card->qdio.out_qs = |
| 3209 | kmalloc(card->qdio.no_out_queues * | 3202 | kmalloc(card->qdio.no_out_queues * |
| 3210 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); | 3203 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); |
| 3211 | if (!card->qdio.out_qs){ | 3204 | if (!card->qdio.out_qs) |
| 3212 | qeth_free_buffer_pool(card); | 3205 | goto out_freepool; |
| 3213 | return -ENOMEM; | 3206 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
| 3214 | } | ||
| 3215 | for (i = 0; i < card->qdio.no_out_queues; ++i){ | ||
| 3216 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), | 3207 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), |
| 3217 | GFP_KERNEL|GFP_DMA); | 3208 | GFP_KERNEL|GFP_DMA); |
| 3218 | if (!card->qdio.out_qs[i]){ | 3209 | if (!card->qdio.out_qs[i]) |
| 3219 | while (i > 0) | 3210 | goto out_freeoutq; |
| 3220 | kfree(card->qdio.out_qs[--i]); | ||
| 3221 | kfree(card->qdio.out_qs); | ||
| 3222 | return -ENOMEM; | ||
| 3223 | } | ||
| 3224 | QETH_DBF_TEXT_(setup, 2, "outq %i", i); | 3211 | QETH_DBF_TEXT_(setup, 2, "outq %i", i); |
| 3225 | QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *)); | 3212 | QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *)); |
| 3226 | memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); | 3213 | memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); |
| @@ -3237,8 +3224,19 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
| 3237 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); | 3224 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); |
| 3238 | } | 3225 | } |
| 3239 | } | 3226 | } |
| 3240 | card->qdio.state = QETH_QDIO_ALLOCATED; | ||
| 3241 | return 0; | 3227 | return 0; |
| 3228 | |||
| 3229 | out_freeoutq: | ||
| 3230 | while (i > 0) | ||
| 3231 | kfree(card->qdio.out_qs[--i]); | ||
| 3232 | kfree(card->qdio.out_qs); | ||
| 3233 | out_freepool: | ||
| 3234 | qeth_free_buffer_pool(card); | ||
| 3235 | out_freeinq: | ||
| 3236 | kfree(card->qdio.in_q); | ||
| 3237 | out_nomem: | ||
| 3238 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); | ||
| 3239 | return -ENOMEM; | ||
| 3242 | } | 3240 | } |
| 3243 | 3241 | ||
| 3244 | static void | 3242 | static void |
| @@ -3247,7 +3245,8 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
| 3247 | int i, j; | 3245 | int i, j; |
| 3248 | 3246 | ||
| 3249 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); | 3247 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); |
| 3250 | if (card->qdio.state == QETH_QDIO_UNINITIALIZED) | 3248 | if (atomic_swap(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == |
| 3249 | QETH_QDIO_UNINITIALIZED) | ||
| 3251 | return; | 3250 | return; |
| 3252 | kfree(card->qdio.in_q); | 3251 | kfree(card->qdio.in_q); |
| 3253 | /* inbound buffer pool */ | 3252 | /* inbound buffer pool */ |
| @@ -3260,7 +3259,6 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
| 3260 | kfree(card->qdio.out_qs[i]); | 3259 | kfree(card->qdio.out_qs[i]); |
| 3261 | } | 3260 | } |
| 3262 | kfree(card->qdio.out_qs); | 3261 | kfree(card->qdio.out_qs); |
| 3263 | card->qdio.state = QETH_QDIO_UNINITIALIZED; | ||
| 3264 | } | 3262 | } |
| 3265 | 3263 | ||
| 3266 | static void | 3264 | static void |
| @@ -3282,7 +3280,7 @@ static void | |||
| 3282 | qeth_init_qdio_info(struct qeth_card *card) | 3280 | qeth_init_qdio_info(struct qeth_card *card) |
| 3283 | { | 3281 | { |
| 3284 | QETH_DBF_TEXT(setup, 4, "intqdinf"); | 3282 | QETH_DBF_TEXT(setup, 4, "intqdinf"); |
| 3285 | card->qdio.state = QETH_QDIO_UNINITIALIZED; | 3283 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); |
| 3286 | /* inbound */ | 3284 | /* inbound */ |
| 3287 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; | 3285 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; |
| 3288 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; | 3286 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; |
| @@ -3345,7 +3343,7 @@ qeth_qdio_establish(struct qeth_card *card) | |||
| 3345 | struct qdio_buffer **in_sbal_ptrs; | 3343 | struct qdio_buffer **in_sbal_ptrs; |
| 3346 | struct qdio_buffer **out_sbal_ptrs; | 3344 | struct qdio_buffer **out_sbal_ptrs; |
| 3347 | int i, j, k; | 3345 | int i, j, k; |
| 3348 | int rc; | 3346 | int rc = 0; |
| 3349 | 3347 | ||
| 3350 | QETH_DBF_TEXT(setup, 2, "qdioest"); | 3348 | QETH_DBF_TEXT(setup, 2, "qdioest"); |
| 3351 | 3349 | ||
| @@ -3404,8 +3402,10 @@ qeth_qdio_establish(struct qeth_card *card) | |||
| 3404 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3402 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
| 3405 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3403 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
| 3406 | 3404 | ||
| 3407 | if (!(rc = qdio_initialize(&init_data))) | 3405 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
| 3408 | card->qdio.state = QETH_QDIO_ESTABLISHED; | 3406 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) |
| 3407 | if ((rc = qdio_initialize(&init_data))) | ||
| 3408 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | ||
| 3409 | 3409 | ||
| 3410 | kfree(out_sbal_ptrs); | 3410 | kfree(out_sbal_ptrs); |
| 3411 | kfree(in_sbal_ptrs); | 3411 | kfree(in_sbal_ptrs); |
| @@ -3521,13 +3521,20 @@ qeth_qdio_clear_card(struct qeth_card *card, int use_halt) | |||
| 3521 | int rc = 0; | 3521 | int rc = 0; |
| 3522 | 3522 | ||
| 3523 | QETH_DBF_TEXT(trace,3,"qdioclr"); | 3523 | QETH_DBF_TEXT(trace,3,"qdioclr"); |
| 3524 | if (card->qdio.state == QETH_QDIO_ESTABLISHED){ | 3524 | switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED, |
| 3525 | QETH_QDIO_CLEANING)) { | ||
| 3526 | case QETH_QDIO_ESTABLISHED: | ||
| 3525 | if ((rc = qdio_cleanup(CARD_DDEV(card), | 3527 | if ((rc = qdio_cleanup(CARD_DDEV(card), |
| 3526 | (card->info.type == QETH_CARD_TYPE_IQD) ? | 3528 | (card->info.type == QETH_CARD_TYPE_IQD) ? |
| 3527 | QDIO_FLAG_CLEANUP_USING_HALT : | 3529 | QDIO_FLAG_CLEANUP_USING_HALT : |
| 3528 | QDIO_FLAG_CLEANUP_USING_CLEAR))) | 3530 | QDIO_FLAG_CLEANUP_USING_CLEAR))) |
| 3529 | QETH_DBF_TEXT_(trace, 3, "1err%d", rc); | 3531 | QETH_DBF_TEXT_(trace, 3, "1err%d", rc); |
| 3530 | card->qdio.state = QETH_QDIO_ALLOCATED; | 3532 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 3533 | break; | ||
| 3534 | case QETH_QDIO_CLEANING: | ||
| 3535 | return rc; | ||
| 3536 | default: | ||
| 3537 | break; | ||
| 3531 | } | 3538 | } |
| 3532 | if ((rc = qeth_clear_halt_card(card, use_halt))) | 3539 | if ((rc = qeth_clear_halt_card(card, use_halt))) |
| 3533 | QETH_DBF_TEXT_(trace, 3, "2err%d", rc); | 3540 | QETH_DBF_TEXT_(trace, 3, "2err%d", rc); |
| @@ -3687,10 +3694,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 3687 | /* return OK; otherwise ksoftirqd goes to 100% */ | 3694 | /* return OK; otherwise ksoftirqd goes to 100% */ |
| 3688 | return NETDEV_TX_OK; | 3695 | return NETDEV_TX_OK; |
| 3689 | } | 3696 | } |
| 3690 | #ifdef CONFIG_QETH_PERF_STATS | 3697 | if (card->options.performance_stats) { |
| 3691 | card->perf_stats.outbound_cnt++; | 3698 | card->perf_stats.outbound_cnt++; |
| 3692 | card->perf_stats.outbound_start_time = qeth_get_micros(); | 3699 | card->perf_stats.outbound_start_time = qeth_get_micros(); |
| 3693 | #endif | 3700 | } |
| 3694 | netif_stop_queue(dev); | 3701 | netif_stop_queue(dev); |
| 3695 | if ((rc = qeth_send_packet(card, skb))) { | 3702 | if ((rc = qeth_send_packet(card, skb))) { |
| 3696 | if (rc == -EBUSY) { | 3703 | if (rc == -EBUSY) { |
| @@ -3704,10 +3711,9 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 3704 | } | 3711 | } |
| 3705 | } | 3712 | } |
| 3706 | netif_wake_queue(dev); | 3713 | netif_wake_queue(dev); |
| 3707 | #ifdef CONFIG_QETH_PERF_STATS | 3714 | if (card->options.performance_stats) |
| 3708 | card->perf_stats.outbound_time += qeth_get_micros() - | 3715 | card->perf_stats.outbound_time += qeth_get_micros() - |
| 3709 | card->perf_stats.outbound_start_time; | 3716 | card->perf_stats.outbound_start_time; |
| 3710 | #endif | ||
| 3711 | return rc; | 3717 | return rc; |
| 3712 | } | 3718 | } |
| 3713 | 3719 | ||
| @@ -3922,49 +3928,59 @@ qeth_get_ip_version(struct sk_buff *skb) | |||
| 3922 | } | 3928 | } |
| 3923 | } | 3929 | } |
| 3924 | 3930 | ||
| 3925 | static inline int | 3931 | static inline struct qeth_hdr * |
| 3926 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, | 3932 | __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) |
| 3927 | struct qeth_hdr **hdr, int ipv) | ||
| 3928 | { | 3933 | { |
| 3929 | int rc = 0; | ||
| 3930 | #ifdef CONFIG_QETH_VLAN | 3934 | #ifdef CONFIG_QETH_VLAN |
| 3931 | u16 *tag; | 3935 | u16 *tag; |
| 3932 | #endif | 3936 | if (card->vlangrp && vlan_tx_tag_present(skb) && |
| 3933 | |||
| 3934 | QETH_DBF_TEXT(trace, 6, "prepskb"); | ||
| 3935 | if (card->info.type == QETH_CARD_TYPE_OSN) { | ||
| 3936 | *hdr = (struct qeth_hdr *)(*skb)->data; | ||
| 3937 | return rc; | ||
| 3938 | } | ||
| 3939 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
| 3940 | if (rc) | ||
| 3941 | return rc; | ||
| 3942 | #ifdef CONFIG_QETH_VLAN | ||
| 3943 | if (card->vlangrp && vlan_tx_tag_present(*skb) && | ||
| 3944 | ((ipv == 6) || card->options.layer2) ) { | 3937 | ((ipv == 6) || card->options.layer2) ) { |
| 3945 | /* | 3938 | /* |
| 3946 | * Move the mac addresses (6 bytes src, 6 bytes dest) | 3939 | * Move the mac addresses (6 bytes src, 6 bytes dest) |
| 3947 | * to the beginning of the new header. We are using three | 3940 | * to the beginning of the new header. We are using three |
| 3948 | * memcpys instead of one memmove to save cycles. | 3941 | * memcpys instead of one memmove to save cycles. |
| 3949 | */ | 3942 | */ |
| 3950 | skb_push(*skb, VLAN_HLEN); | 3943 | skb_push(skb, VLAN_HLEN); |
| 3951 | memcpy((*skb)->data, (*skb)->data + 4, 4); | 3944 | memcpy(skb->data, skb->data + 4, 4); |
| 3952 | memcpy((*skb)->data + 4, (*skb)->data + 8, 4); | 3945 | memcpy(skb->data + 4, skb->data + 8, 4); |
| 3953 | memcpy((*skb)->data + 8, (*skb)->data + 12, 4); | 3946 | memcpy(skb->data + 8, skb->data + 12, 4); |
| 3954 | tag = (u16 *)((*skb)->data + 12); | 3947 | tag = (u16 *)(skb->data + 12); |
| 3955 | /* | 3948 | /* |
| 3956 | * first two bytes = ETH_P_8021Q (0x8100) | 3949 | * first two bytes = ETH_P_8021Q (0x8100) |
| 3957 | * second two bytes = VLANID | 3950 | * second two bytes = VLANID |
| 3958 | */ | 3951 | */ |
| 3959 | *tag = __constant_htons(ETH_P_8021Q); | 3952 | *tag = __constant_htons(ETH_P_8021Q); |
| 3960 | *(tag + 1) = htons(vlan_tx_tag_get(*skb)); | 3953 | *(tag + 1) = htons(vlan_tx_tag_get(skb)); |
| 3961 | } | 3954 | } |
| 3962 | #endif | 3955 | #endif |
| 3963 | *hdr = (struct qeth_hdr *) | 3956 | return ((struct qeth_hdr *) |
| 3964 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr)); | 3957 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); |
| 3965 | if (*hdr == NULL) | 3958 | } |
| 3966 | return -EINVAL; | 3959 | |
| 3967 | return 0; | 3960 | static inline void |
| 3961 | __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) | ||
| 3962 | { | ||
| 3963 | if (orig_skb != new_skb) | ||
| 3964 | dev_kfree_skb_any(new_skb); | ||
| 3965 | } | ||
| 3966 | |||
| 3967 | static inline struct sk_buff * | ||
| 3968 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, | ||
| 3969 | struct qeth_hdr **hdr, int ipv) | ||
| 3970 | { | ||
| 3971 | struct sk_buff *new_skb; | ||
| 3972 | |||
| 3973 | QETH_DBF_TEXT(trace, 6, "prepskb"); | ||
| 3974 | |||
| 3975 | new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
| 3976 | if (new_skb == NULL) | ||
| 3977 | return NULL; | ||
| 3978 | *hdr = __qeth_prepare_skb(card, new_skb, ipv); | ||
| 3979 | if (*hdr == NULL) { | ||
| 3980 | __qeth_free_new_skb(skb, new_skb); | ||
| 3981 | return NULL; | ||
| 3982 | } | ||
| 3983 | return new_skb; | ||
| 3968 | } | 3984 | } |
| 3969 | 3985 | ||
| 3970 | static inline u8 | 3986 | static inline u8 |
| @@ -4206,9 +4222,8 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
| 4206 | flush_cnt = 1; | 4222 | flush_cnt = 1; |
| 4207 | } else { | 4223 | } else { |
| 4208 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); | 4224 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); |
| 4209 | #ifdef CONFIG_QETH_PERF_STATS | 4225 | if (queue->card->options.performance_stats) |
| 4210 | queue->card->perf_stats.skbs_sent_pack++; | 4226 | queue->card->perf_stats.skbs_sent_pack++; |
| 4211 | #endif | ||
| 4212 | if (buf->next_element_to_fill >= | 4227 | if (buf->next_element_to_fill >= |
| 4213 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { | 4228 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { |
| 4214 | /* | 4229 | /* |
| @@ -4245,21 +4260,15 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4245 | * check if buffer is empty to make sure that we do not 'overtake' | 4260 | * check if buffer is empty to make sure that we do not 'overtake' |
| 4246 | * ourselves and try to fill a buffer that is already primed | 4261 | * ourselves and try to fill a buffer that is already primed |
| 4247 | */ | 4262 | */ |
| 4248 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { | 4263 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) |
| 4249 | card->stats.tx_dropped++; | 4264 | goto out; |
| 4250 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
| 4251 | return -EBUSY; | ||
| 4252 | } | ||
| 4253 | if (ctx == NULL) | 4265 | if (ctx == NULL) |
| 4254 | queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % | 4266 | queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % |
| 4255 | QDIO_MAX_BUFFERS_PER_Q; | 4267 | QDIO_MAX_BUFFERS_PER_Q; |
| 4256 | else { | 4268 | else { |
| 4257 | buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx); | 4269 | buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx); |
| 4258 | if (buffers_needed < 0) { | 4270 | if (buffers_needed < 0) |
| 4259 | card->stats.tx_dropped++; | 4271 | goto out; |
| 4260 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
| 4261 | return -EBUSY; | ||
| 4262 | } | ||
| 4263 | queue->next_buf_to_fill = | 4272 | queue->next_buf_to_fill = |
| 4264 | (queue->next_buf_to_fill + buffers_needed) % | 4273 | (queue->next_buf_to_fill + buffers_needed) % |
| 4265 | QDIO_MAX_BUFFERS_PER_Q; | 4274 | QDIO_MAX_BUFFERS_PER_Q; |
| @@ -4274,6 +4283,9 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4274 | qeth_flush_buffers(queue, 0, index, flush_cnt); | 4283 | qeth_flush_buffers(queue, 0, index, flush_cnt); |
| 4275 | } | 4284 | } |
| 4276 | return 0; | 4285 | return 0; |
| 4286 | out: | ||
| 4287 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
| 4288 | return -EBUSY; | ||
| 4277 | } | 4289 | } |
| 4278 | 4290 | ||
| 4279 | static inline int | 4291 | static inline int |
| @@ -4299,8 +4311,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4299 | * check if buffer is empty to make sure that we do not 'overtake' | 4311 | * check if buffer is empty to make sure that we do not 'overtake' |
| 4300 | * ourselves and try to fill a buffer that is already primed | 4312 | * ourselves and try to fill a buffer that is already primed |
| 4301 | */ | 4313 | */ |
| 4302 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ | 4314 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { |
| 4303 | card->stats.tx_dropped++; | ||
| 4304 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 4315 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
| 4305 | return -EBUSY; | 4316 | return -EBUSY; |
| 4306 | } | 4317 | } |
| @@ -4323,7 +4334,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4323 | * again */ | 4334 | * again */ |
| 4324 | if (atomic_read(&buffer->state) != | 4335 | if (atomic_read(&buffer->state) != |
| 4325 | QETH_QDIO_BUF_EMPTY){ | 4336 | QETH_QDIO_BUF_EMPTY){ |
| 4326 | card->stats.tx_dropped++; | ||
| 4327 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4337 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
| 4328 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 4338 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
| 4329 | return -EBUSY; | 4339 | return -EBUSY; |
| @@ -4334,7 +4344,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4334 | * free buffers) to handle eddp context */ | 4344 | * free buffers) to handle eddp context */ |
| 4335 | if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){ | 4345 | if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){ |
| 4336 | printk("eddp tx_dropped 1\n"); | 4346 | printk("eddp tx_dropped 1\n"); |
| 4337 | card->stats.tx_dropped++; | ||
| 4338 | rc = -EBUSY; | 4347 | rc = -EBUSY; |
| 4339 | goto out; | 4348 | goto out; |
| 4340 | } | 4349 | } |
| @@ -4346,7 +4355,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
| 4346 | tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill); | 4355 | tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill); |
| 4347 | if (tmp < 0) { | 4356 | if (tmp < 0) { |
| 4348 | printk("eddp tx_dropped 2\n"); | 4357 | printk("eddp tx_dropped 2\n"); |
| 4349 | card->stats.tx_dropped++; | ||
| 4350 | rc = - EBUSY; | 4358 | rc = - EBUSY; |
| 4351 | goto out; | 4359 | goto out; |
| 4352 | } | 4360 | } |
| @@ -4380,10 +4388,8 @@ out: | |||
| 4380 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4388 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
| 4381 | } | 4389 | } |
| 4382 | /* at this point the queue is UNLOCKED again */ | 4390 | /* at this point the queue is UNLOCKED again */ |
| 4383 | #ifdef CONFIG_QETH_PERF_STATS | 4391 | if (queue->card->options.performance_stats && do_pack) |
| 4384 | if (do_pack) | ||
| 4385 | queue->card->perf_stats.bufs_sent_pack += flush_count; | 4392 | queue->card->perf_stats.bufs_sent_pack += flush_count; |
| 4386 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
| 4387 | 4393 | ||
| 4388 | return rc; | 4394 | return rc; |
| 4389 | } | 4395 | } |
| @@ -4394,21 +4400,21 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, | |||
| 4394 | { | 4400 | { |
| 4395 | int elements_needed = 0; | 4401 | int elements_needed = 0; |
| 4396 | 4402 | ||
| 4397 | if (skb_shinfo(skb)->nr_frags > 0) { | 4403 | if (skb_shinfo(skb)->nr_frags > 0) |
| 4398 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); | 4404 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); |
| 4399 | } | 4405 | if (elements_needed == 0) |
| 4400 | if (elements_needed == 0 ) | ||
| 4401 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) | 4406 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) |
| 4402 | + skb->len) >> PAGE_SHIFT); | 4407 | + skb->len) >> PAGE_SHIFT); |
| 4403 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ | 4408 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ |
| 4404 | PRINT_ERR("qeth_do_send_packet: invalid size of " | 4409 | PRINT_ERR("Invalid size of IP packet " |
| 4405 | "IP packet (Number=%d / Length=%d). Discarded.\n", | 4410 | "(Number=%d / Length=%d). Discarded.\n", |
| 4406 | (elements_needed+elems), skb->len); | 4411 | (elements_needed+elems), skb->len); |
| 4407 | return 0; | 4412 | return 0; |
| 4408 | } | 4413 | } |
| 4409 | return elements_needed; | 4414 | return elements_needed; |
| 4410 | } | 4415 | } |
| 4411 | 4416 | ||
| 4417 | |||
| 4412 | static inline int | 4418 | static inline int |
| 4413 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | 4419 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) |
| 4414 | { | 4420 | { |
| @@ -4420,112 +4426,112 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
| 4420 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 4426 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
| 4421 | struct qeth_eddp_context *ctx = NULL; | 4427 | struct qeth_eddp_context *ctx = NULL; |
| 4422 | int tx_bytes = skb->len; | 4428 | int tx_bytes = skb->len; |
| 4423 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 4424 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; | 4429 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; |
| 4425 | unsigned short tso_size = skb_shinfo(skb)->gso_size; | 4430 | unsigned short tso_size = skb_shinfo(skb)->gso_size; |
| 4426 | #endif | 4431 | struct sk_buff *new_skb, *new_skb2; |
| 4427 | int rc; | 4432 | int rc; |
| 4428 | 4433 | ||
| 4429 | QETH_DBF_TEXT(trace, 6, "sendpkt"); | 4434 | QETH_DBF_TEXT(trace, 6, "sendpkt"); |
| 4430 | 4435 | ||
| 4436 | new_skb = skb; | ||
| 4437 | if ((card->info.type == QETH_CARD_TYPE_OSN) && | ||
| 4438 | (skb->protocol == htons(ETH_P_IPV6))) | ||
| 4439 | return -EPERM; | ||
| 4440 | cast_type = qeth_get_cast_type(card, skb); | ||
| 4441 | if ((cast_type == RTN_BROADCAST) && | ||
| 4442 | (card->info.broadcast_capable == 0)) | ||
| 4443 | return -EPERM; | ||
| 4444 | queue = card->qdio.out_qs | ||
| 4445 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | ||
| 4431 | if (!card->options.layer2) { | 4446 | if (!card->options.layer2) { |
| 4432 | ipv = qeth_get_ip_version(skb); | 4447 | ipv = qeth_get_ip_version(skb); |
| 4433 | if ((card->dev->hard_header == qeth_fake_header) && ipv) { | 4448 | if ((card->dev->hard_header == qeth_fake_header) && ipv) { |
| 4434 | if ((skb = qeth_pskb_unshare(skb,GFP_ATOMIC)) == NULL) { | 4449 | new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC); |
| 4435 | card->stats.tx_dropped++; | 4450 | if (!new_skb) |
| 4436 | dev_kfree_skb_irq(skb); | 4451 | return -ENOMEM; |
| 4437 | return 0; | ||
| 4438 | } | ||
| 4439 | if(card->dev->type == ARPHRD_IEEE802_TR){ | 4452 | if(card->dev->type == ARPHRD_IEEE802_TR){ |
| 4440 | skb_pull(skb, QETH_FAKE_LL_LEN_TR); | 4453 | skb_pull(new_skb, QETH_FAKE_LL_LEN_TR); |
| 4441 | } else { | 4454 | } else { |
| 4442 | skb_pull(skb, QETH_FAKE_LL_LEN_ETH); | 4455 | skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH); |
| 4443 | } | 4456 | } |
| 4444 | } | 4457 | } |
| 4445 | } | 4458 | } |
| 4446 | if ((card->info.type == QETH_CARD_TYPE_OSN) && | ||
| 4447 | (skb->protocol == htons(ETH_P_IPV6))) { | ||
| 4448 | dev_kfree_skb_any(skb); | ||
| 4449 | return 0; | ||
| 4450 | } | ||
| 4451 | cast_type = qeth_get_cast_type(card, skb); | ||
| 4452 | if ((cast_type == RTN_BROADCAST) && | ||
| 4453 | (card->info.broadcast_capable == 0)){ | ||
| 4454 | card->stats.tx_dropped++; | ||
| 4455 | card->stats.tx_errors++; | ||
| 4456 | dev_kfree_skb_any(skb); | ||
| 4457 | return NETDEV_TX_OK; | ||
| 4458 | } | ||
| 4459 | queue = card->qdio.out_qs | ||
| 4460 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | ||
| 4461 | |||
| 4462 | if (skb_is_gso(skb)) | 4459 | if (skb_is_gso(skb)) |
| 4463 | large_send = card->options.large_send; | 4460 | large_send = card->options.large_send; |
| 4464 | 4461 | /* check on OSN device*/ | |
| 4465 | /*are we able to do TSO ? If so ,prepare and send it from here */ | 4462 | if (card->info.type == QETH_CARD_TYPE_OSN) |
| 4463 | hdr = (struct qeth_hdr *)new_skb->data; | ||
| 4464 | /*are we able to do TSO ? */ | ||
| 4466 | if ((large_send == QETH_LARGE_SEND_TSO) && | 4465 | if ((large_send == QETH_LARGE_SEND_TSO) && |
| 4467 | (cast_type == RTN_UNSPEC)) { | 4466 | (cast_type == RTN_UNSPEC)) { |
| 4468 | rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type); | 4467 | rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type); |
| 4469 | if (rc) { | 4468 | if (rc) { |
| 4470 | card->stats.tx_dropped++; | 4469 | __qeth_free_new_skb(skb, new_skb); |
| 4471 | card->stats.tx_errors++; | 4470 | return rc; |
| 4472 | dev_kfree_skb_any(skb); | ||
| 4473 | return NETDEV_TX_OK; | ||
| 4474 | } | 4471 | } |
| 4475 | elements_needed++; | 4472 | elements_needed++; |
| 4476 | } else { | 4473 | } else if (card->info.type != QETH_CARD_TYPE_OSN) { |
| 4477 | if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) { | 4474 | new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv); |
| 4478 | QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); | 4475 | if (!new_skb2) { |
| 4479 | return rc; | 4476 | __qeth_free_new_skb(skb, new_skb); |
| 4477 | return -EINVAL; | ||
| 4480 | } | 4478 | } |
| 4481 | if (card->info.type != QETH_CARD_TYPE_OSN) | 4479 | if (new_skb != skb) |
| 4482 | qeth_fill_header(card, hdr, skb, ipv, cast_type); | 4480 | __qeth_free_new_skb(new_skb2, new_skb); |
| 4481 | new_skb = new_skb2; | ||
| 4482 | qeth_fill_header(card, hdr, new_skb, ipv, cast_type); | ||
| 4483 | } | 4483 | } |
| 4484 | |||
| 4485 | if (large_send == QETH_LARGE_SEND_EDDP) { | 4484 | if (large_send == QETH_LARGE_SEND_EDDP) { |
| 4486 | ctx = qeth_eddp_create_context(card, skb, hdr); | 4485 | ctx = qeth_eddp_create_context(card, new_skb, hdr); |
| 4487 | if (ctx == NULL) { | 4486 | if (ctx == NULL) { |
| 4487 | __qeth_free_new_skb(skb, new_skb); | ||
| 4488 | PRINT_WARN("could not create eddp context\n"); | 4488 | PRINT_WARN("could not create eddp context\n"); |
| 4489 | return -EINVAL; | 4489 | return -EINVAL; |
| 4490 | } | 4490 | } |
| 4491 | } else { | 4491 | } else { |
| 4492 | int elems = qeth_get_elements_no(card,(void*) hdr, skb, | 4492 | int elems = qeth_get_elements_no(card,(void*) hdr, new_skb, |
| 4493 | elements_needed); | 4493 | elements_needed); |
| 4494 | if (!elems) | 4494 | if (!elems) { |
| 4495 | __qeth_free_new_skb(skb, new_skb); | ||
| 4495 | return -EINVAL; | 4496 | return -EINVAL; |
| 4497 | } | ||
| 4496 | elements_needed += elems; | 4498 | elements_needed += elems; |
| 4497 | } | 4499 | } |
| 4498 | 4500 | ||
| 4499 | if (card->info.type != QETH_CARD_TYPE_IQD) | 4501 | if (card->info.type != QETH_CARD_TYPE_IQD) |
| 4500 | rc = qeth_do_send_packet(card, queue, skb, hdr, | 4502 | rc = qeth_do_send_packet(card, queue, new_skb, hdr, |
| 4501 | elements_needed, ctx); | 4503 | elements_needed, ctx); |
| 4502 | else | 4504 | else |
| 4503 | rc = qeth_do_send_packet_fast(card, queue, skb, hdr, | 4505 | rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, |
| 4504 | elements_needed, ctx); | 4506 | elements_needed, ctx); |
| 4505 | if (!rc){ | 4507 | if (!rc) { |
| 4506 | card->stats.tx_packets++; | 4508 | card->stats.tx_packets++; |
| 4507 | card->stats.tx_bytes += tx_bytes; | 4509 | card->stats.tx_bytes += tx_bytes; |
| 4508 | #ifdef CONFIG_QETH_PERF_STATS | 4510 | if (new_skb != skb) |
| 4509 | if (tso_size && | 4511 | dev_kfree_skb_any(skb); |
| 4510 | !(large_send == QETH_LARGE_SEND_NO)) { | 4512 | if (card->options.performance_stats) { |
| 4511 | card->perf_stats.large_send_bytes += tx_bytes; | 4513 | if (tso_size && |
| 4512 | card->perf_stats.large_send_cnt++; | 4514 | !(large_send == QETH_LARGE_SEND_NO)) { |
| 4513 | } | 4515 | card->perf_stats.large_send_bytes += tx_bytes; |
| 4514 | if (nr_frags > 0){ | 4516 | card->perf_stats.large_send_cnt++; |
| 4515 | card->perf_stats.sg_skbs_sent++; | 4517 | } |
| 4516 | /* nr_frags + skb->data */ | 4518 | if (nr_frags > 0) { |
| 4517 | card->perf_stats.sg_frags_sent += | 4519 | card->perf_stats.sg_skbs_sent++; |
| 4518 | nr_frags + 1; | 4520 | /* nr_frags + skb->data */ |
| 4521 | card->perf_stats.sg_frags_sent += | ||
| 4522 | nr_frags + 1; | ||
| 4523 | } | ||
| 4519 | } | 4524 | } |
| 4520 | #endif /* CONFIG_QETH_PERF_STATS */ | 4525 | } else { |
| 4526 | card->stats.tx_dropped++; | ||
| 4527 | __qeth_free_new_skb(skb, new_skb); | ||
| 4521 | } | 4528 | } |
| 4522 | if (ctx != NULL) { | 4529 | if (ctx != NULL) { |
| 4523 | /* drop creator's reference */ | 4530 | /* drop creator's reference */ |
| 4524 | qeth_eddp_put_context(ctx); | 4531 | qeth_eddp_put_context(ctx); |
| 4525 | /* free skb; it's not referenced by a buffer */ | 4532 | /* free skb; it's not referenced by a buffer */ |
| 4526 | if (rc == 0) | 4533 | if (!rc) |
| 4527 | dev_kfree_skb_any(skb); | 4534 | dev_kfree_skb_any(new_skb); |
| 4528 | |||
| 4529 | } | 4535 | } |
| 4530 | return rc; | 4536 | return rc; |
| 4531 | } | 4537 | } |
| @@ -7338,6 +7344,8 @@ qeth_setrouting_v6(struct qeth_card *card) | |||
| 7338 | QETH_DBF_TEXT(trace,3,"setrtg6"); | 7344 | QETH_DBF_TEXT(trace,3,"setrtg6"); |
| 7339 | #ifdef CONFIG_QETH_IPV6 | 7345 | #ifdef CONFIG_QETH_IPV6 |
| 7340 | 7346 | ||
| 7347 | if (!qeth_is_supported(card, IPA_IPV6)) | ||
| 7348 | return 0; | ||
| 7341 | qeth_correct_routing_type(card, &card->options.route6.type, | 7349 | qeth_correct_routing_type(card, &card->options.route6.type, |
| 7342 | QETH_PROT_IPV6); | 7350 | QETH_PROT_IPV6); |
| 7343 | 7351 | ||
| @@ -7876,12 +7884,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
| 7876 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 7884 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
| 7877 | goto out_remove; | 7885 | goto out_remove; |
| 7878 | } | 7886 | } |
| 7879 | card->state = CARD_STATE_SOFTSETUP; | ||
| 7880 | 7887 | ||
| 7881 | if ((rc = qeth_init_qdio_queues(card))){ | 7888 | if ((rc = qeth_init_qdio_queues(card))){ |
| 7882 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 7889 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
| 7883 | goto out_remove; | 7890 | goto out_remove; |
| 7884 | } | 7891 | } |
| 7892 | card->state = CARD_STATE_SOFTSETUP; | ||
| 7885 | netif_carrier_on(card->dev); | 7893 | netif_carrier_on(card->dev); |
| 7886 | 7894 | ||
| 7887 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 7895 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
| @@ -8538,34 +8546,44 @@ qeth_ipv6_uninit(void) | |||
| 8538 | static void | 8546 | static void |
| 8539 | qeth_sysfs_unregister(void) | 8547 | qeth_sysfs_unregister(void) |
| 8540 | { | 8548 | { |
| 8549 | s390_root_dev_unregister(qeth_root_dev); | ||
| 8541 | qeth_remove_driver_attributes(); | 8550 | qeth_remove_driver_attributes(); |
| 8542 | ccw_driver_unregister(&qeth_ccw_driver); | 8551 | ccw_driver_unregister(&qeth_ccw_driver); |
| 8543 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); | 8552 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); |
| 8544 | s390_root_dev_unregister(qeth_root_dev); | ||
| 8545 | } | 8553 | } |
| 8554 | |||
| 8546 | /** | 8555 | /** |
| 8547 | * register qeth at sysfs | 8556 | * register qeth at sysfs |
| 8548 | */ | 8557 | */ |
| 8549 | static int | 8558 | static int |
| 8550 | qeth_sysfs_register(void) | 8559 | qeth_sysfs_register(void) |
| 8551 | { | 8560 | { |
| 8552 | int rc=0; | 8561 | int rc; |
| 8553 | 8562 | ||
| 8554 | rc = ccwgroup_driver_register(&qeth_ccwgroup_driver); | 8563 | rc = ccwgroup_driver_register(&qeth_ccwgroup_driver); |
| 8555 | if (rc) | 8564 | if (rc) |
| 8556 | return rc; | 8565 | goto out; |
| 8566 | |||
| 8557 | rc = ccw_driver_register(&qeth_ccw_driver); | 8567 | rc = ccw_driver_register(&qeth_ccw_driver); |
| 8558 | if (rc) | 8568 | if (rc) |
| 8559 | return rc; | 8569 | goto out_ccw_driver; |
| 8570 | |||
| 8560 | rc = qeth_create_driver_attributes(); | 8571 | rc = qeth_create_driver_attributes(); |
| 8561 | if (rc) | 8572 | if (rc) |
| 8562 | return rc; | 8573 | goto out_qeth_attr; |
| 8574 | |||
| 8563 | qeth_root_dev = s390_root_dev_register("qeth"); | 8575 | qeth_root_dev = s390_root_dev_register("qeth"); |
| 8564 | if (IS_ERR(qeth_root_dev)) { | 8576 | rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0; |
| 8565 | rc = PTR_ERR(qeth_root_dev); | 8577 | if (!rc) |
| 8566 | return rc; | 8578 | goto out; |
| 8567 | } | 8579 | |
| 8568 | return 0; | 8580 | qeth_remove_driver_attributes(); |
| 8581 | out_qeth_attr: | ||
| 8582 | ccw_driver_unregister(&qeth_ccw_driver); | ||
| 8583 | out_ccw_driver: | ||
| 8584 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); | ||
| 8585 | out: | ||
| 8586 | return rc; | ||
| 8569 | } | 8587 | } |
| 8570 | 8588 | ||
| 8571 | /*** | 8589 | /*** |
| @@ -8574,7 +8592,7 @@ qeth_sysfs_register(void) | |||
| 8574 | static int __init | 8592 | static int __init |
| 8575 | qeth_init(void) | 8593 | qeth_init(void) |
| 8576 | { | 8594 | { |
| 8577 | int rc=0; | 8595 | int rc; |
| 8578 | 8596 | ||
| 8579 | PRINT_INFO("loading %s\n", version); | 8597 | PRINT_INFO("loading %s\n", version); |
| 8580 | 8598 | ||
| @@ -8583,20 +8601,26 @@ qeth_init(void) | |||
| 8583 | spin_lock_init(&qeth_notify_lock); | 8601 | spin_lock_init(&qeth_notify_lock); |
| 8584 | rwlock_init(&qeth_card_list.rwlock); | 8602 | rwlock_init(&qeth_card_list.rwlock); |
| 8585 | 8603 | ||
| 8586 | if (qeth_register_dbf_views()) | 8604 | rc = qeth_register_dbf_views(); |
| 8605 | if (rc) | ||
| 8587 | goto out_err; | 8606 | goto out_err; |
| 8588 | if (qeth_sysfs_register()) | 8607 | |
| 8589 | goto out_sysfs; | 8608 | rc = qeth_sysfs_register(); |
| 8609 | if (rc) | ||
| 8610 | goto out_dbf; | ||
| 8590 | 8611 | ||
| 8591 | #ifdef CONFIG_QETH_IPV6 | 8612 | #ifdef CONFIG_QETH_IPV6 |
| 8592 | if (qeth_ipv6_init()) { | 8613 | rc = qeth_ipv6_init(); |
| 8593 | PRINT_ERR("Out of memory during ipv6 init.\n"); | 8614 | if (rc) { |
| 8615 | PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc); | ||
| 8594 | goto out_sysfs; | 8616 | goto out_sysfs; |
| 8595 | } | 8617 | } |
| 8596 | #endif /* QETH_IPV6 */ | 8618 | #endif /* QETH_IPV6 */ |
| 8597 | if (qeth_register_notifiers()) | 8619 | rc = qeth_register_notifiers(); |
| 8620 | if (rc) | ||
| 8598 | goto out_ipv6; | 8621 | goto out_ipv6; |
| 8599 | if (qeth_create_procfs_entries()) | 8622 | rc = qeth_create_procfs_entries(); |
| 8623 | if (rc) | ||
| 8600 | goto out_notifiers; | 8624 | goto out_notifiers; |
| 8601 | 8625 | ||
| 8602 | return rc; | 8626 | return rc; |
| @@ -8606,12 +8630,13 @@ out_notifiers: | |||
| 8606 | out_ipv6: | 8630 | out_ipv6: |
| 8607 | #ifdef CONFIG_QETH_IPV6 | 8631 | #ifdef CONFIG_QETH_IPV6 |
| 8608 | qeth_ipv6_uninit(); | 8632 | qeth_ipv6_uninit(); |
| 8609 | #endif /* QETH_IPV6 */ | ||
| 8610 | out_sysfs: | 8633 | out_sysfs: |
| 8634 | #endif /* QETH_IPV6 */ | ||
| 8611 | qeth_sysfs_unregister(); | 8635 | qeth_sysfs_unregister(); |
| 8636 | out_dbf: | ||
| 8612 | qeth_unregister_dbf_views(); | 8637 | qeth_unregister_dbf_views(); |
| 8613 | out_err: | 8638 | out_err: |
| 8614 | PRINT_ERR("Initialization failed"); | 8639 | PRINT_ERR("Initialization failed with code %d\n", rc); |
| 8615 | return rc; | 8640 | return rc; |
| 8616 | } | 8641 | } |
| 8617 | 8642 | ||
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 66f2da14e6e3..faa768e59257 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c | |||
| @@ -173,7 +173,6 @@ static struct file_operations qeth_procfile_fops = { | |||
| 173 | #define QETH_PERF_PROCFILE_NAME "qeth_perf" | 173 | #define QETH_PERF_PROCFILE_NAME "qeth_perf" |
| 174 | static struct proc_dir_entry *qeth_perf_procfile; | 174 | static struct proc_dir_entry *qeth_perf_procfile; |
| 175 | 175 | ||
| 176 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 177 | static int | 176 | static int |
| 178 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | 177 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) |
| 179 | { | 178 | { |
| @@ -192,14 +191,21 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | |||
| 192 | CARD_DDEV_ID(card), | 191 | CARD_DDEV_ID(card), |
| 193 | QETH_CARD_IFNAME(card) | 192 | QETH_CARD_IFNAME(card) |
| 194 | ); | 193 | ); |
| 194 | if (!card->options.performance_stats) | ||
| 195 | seq_printf(s, "Performance statistics are deactivated.\n"); | ||
| 195 | seq_printf(s, " Skb's/buffers received : %lu/%u\n" | 196 | seq_printf(s, " Skb's/buffers received : %lu/%u\n" |
| 196 | " Skb's/buffers sent : %lu/%u\n\n", | 197 | " Skb's/buffers sent : %lu/%u\n\n", |
| 197 | card->stats.rx_packets, card->perf_stats.bufs_rec, | 198 | card->stats.rx_packets - |
| 198 | card->stats.tx_packets, card->perf_stats.bufs_sent | 199 | card->perf_stats.initial_rx_packets, |
| 200 | card->perf_stats.bufs_rec, | ||
| 201 | card->stats.tx_packets - | ||
| 202 | card->perf_stats.initial_tx_packets, | ||
| 203 | card->perf_stats.bufs_sent | ||
| 199 | ); | 204 | ); |
| 200 | seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" | 205 | seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" |
| 201 | " Skb's/buffers sent with packing : %u/%u\n\n", | 206 | " Skb's/buffers sent with packing : %u/%u\n\n", |
| 202 | card->stats.tx_packets - card->perf_stats.skbs_sent_pack, | 207 | card->stats.tx_packets - card->perf_stats.initial_tx_packets |
| 208 | - card->perf_stats.skbs_sent_pack, | ||
| 203 | card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, | 209 | card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, |
| 204 | card->perf_stats.skbs_sent_pack, | 210 | card->perf_stats.skbs_sent_pack, |
| 205 | card->perf_stats.bufs_sent_pack | 211 | card->perf_stats.bufs_sent_pack |
| @@ -275,11 +281,6 @@ static struct file_operations qeth_perf_procfile_fops = { | |||
| 275 | .release = seq_release, | 281 | .release = seq_release, |
| 276 | }; | 282 | }; |
| 277 | 283 | ||
| 278 | #define qeth_perf_procfile_created qeth_perf_procfile | ||
| 279 | #else | ||
| 280 | #define qeth_perf_procfile_created 1 | ||
| 281 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
| 282 | |||
| 283 | int __init | 284 | int __init |
| 284 | qeth_create_procfs_entries(void) | 285 | qeth_create_procfs_entries(void) |
| 285 | { | 286 | { |
| @@ -288,15 +289,13 @@ qeth_create_procfs_entries(void) | |||
| 288 | if (qeth_procfile) | 289 | if (qeth_procfile) |
| 289 | qeth_procfile->proc_fops = &qeth_procfile_fops; | 290 | qeth_procfile->proc_fops = &qeth_procfile_fops; |
| 290 | 291 | ||
| 291 | #ifdef CONFIG_QETH_PERF_STATS | ||
| 292 | qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME, | 292 | qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME, |
| 293 | S_IFREG | 0444, NULL); | 293 | S_IFREG | 0444, NULL); |
| 294 | if (qeth_perf_procfile) | 294 | if (qeth_perf_procfile) |
| 295 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; | 295 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; |
| 296 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
| 297 | 296 | ||
| 298 | if (qeth_procfile && | 297 | if (qeth_procfile && |
| 299 | qeth_perf_procfile_created) | 298 | qeth_perf_procfile) |
| 300 | return 0; | 299 | return 0; |
| 301 | else | 300 | else |
| 302 | return -ENOMEM; | 301 | return -ENOMEM; |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 001497bbea16..5836737ac58f 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
| @@ -743,6 +743,47 @@ static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, | |||
| 743 | qeth_dev_layer2_store); | 743 | qeth_dev_layer2_store); |
| 744 | 744 | ||
| 745 | static ssize_t | 745 | static ssize_t |
| 746 | qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 747 | { | ||
| 748 | struct qeth_card *card = dev->driver_data; | ||
| 749 | |||
| 750 | if (!card) | ||
| 751 | return -EINVAL; | ||
| 752 | |||
| 753 | return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); | ||
| 754 | } | ||
| 755 | |||
| 756 | static ssize_t | ||
| 757 | qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
| 758 | { | ||
| 759 | struct qeth_card *card = dev->driver_data; | ||
| 760 | char *tmp; | ||
| 761 | int i; | ||
| 762 | |||
| 763 | if (!card) | ||
| 764 | return -EINVAL; | ||
| 765 | |||
| 766 | i = simple_strtoul(buf, &tmp, 16); | ||
| 767 | if ((i == 0) || (i == 1)) { | ||
| 768 | if (i == card->options.performance_stats) | ||
| 769 | return count; | ||
| 770 | card->options.performance_stats = i; | ||
| 771 | if (i == 0) | ||
| 772 | memset(&card->perf_stats, 0, | ||
| 773 | sizeof(struct qeth_perf_stats)); | ||
| 774 | card->perf_stats.initial_rx_packets = card->stats.rx_packets; | ||
| 775 | card->perf_stats.initial_tx_packets = card->stats.tx_packets; | ||
| 776 | } else { | ||
| 777 | PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); | ||
| 778 | return -EINVAL; | ||
| 779 | } | ||
| 780 | return count; | ||
| 781 | } | ||
| 782 | |||
| 783 | static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, | ||
| 784 | qeth_dev_performance_stats_store); | ||
| 785 | |||
| 786 | static ssize_t | ||
| 746 | qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) | 787 | qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) |
| 747 | { | 788 | { |
| 748 | struct qeth_card *card = dev->driver_data; | 789 | struct qeth_card *card = dev->driver_data; |
| @@ -928,6 +969,7 @@ static struct device_attribute * qeth_device_attrs[] = { | |||
| 928 | &dev_attr_canonical_macaddr, | 969 | &dev_attr_canonical_macaddr, |
| 929 | &dev_attr_layer2, | 970 | &dev_attr_layer2, |
| 930 | &dev_attr_large_send, | 971 | &dev_attr_large_send, |
| 972 | &dev_attr_performance_stats, | ||
| 931 | NULL, | 973 | NULL, |
| 932 | }; | 974 | }; |
| 933 | 975 | ||
| @@ -1110,12 +1152,12 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | |||
| 1110 | { | 1152 | { |
| 1111 | const char *start, *end; | 1153 | const char *start, *end; |
| 1112 | char *tmp; | 1154 | char *tmp; |
| 1113 | char buffer[49] = {0, }; | 1155 | char buffer[40] = {0, }; |
| 1114 | 1156 | ||
| 1115 | start = buf; | 1157 | start = buf; |
| 1116 | /* get address string */ | 1158 | /* get address string */ |
| 1117 | end = strchr(start, '/'); | 1159 | end = strchr(start, '/'); |
| 1118 | if (!end || (end-start >= 49)){ | 1160 | if (!end || (end - start >= 40)){ |
| 1119 | PRINT_WARN("Invalid format for ipato_addx/delx. " | 1161 | PRINT_WARN("Invalid format for ipato_addx/delx. " |
| 1120 | "Use <ip addr>/<mask bits>\n"); | 1162 | "Use <ip addr>/<mask bits>\n"); |
| 1121 | return -EINVAL; | 1163 | return -EINVAL; |
| @@ -1127,7 +1169,12 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | |||
| 1127 | } | 1169 | } |
| 1128 | start = end + 1; | 1170 | start = end + 1; |
| 1129 | *mask_bits = simple_strtoul(start, &tmp, 10); | 1171 | *mask_bits = simple_strtoul(start, &tmp, 10); |
| 1130 | 1172 | if (!strlen(start) || | |
| 1173 | (tmp == start) || | ||
| 1174 | (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { | ||
| 1175 | PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); | ||
| 1176 | return -EINVAL; | ||
| 1177 | } | ||
| 1131 | return 0; | 1178 | return 0; |
| 1132 | } | 1179 | } |
| 1133 | 1180 | ||
| @@ -1698,11 +1745,16 @@ qeth_create_device_attributes(struct device *dev) | |||
| 1698 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | 1745 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); |
| 1699 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | 1746 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); |
| 1700 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); | 1747 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); |
| 1748 | return ret; | ||
| 1701 | } | 1749 | } |
| 1702 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))) | 1750 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){ |
| 1751 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
| 1752 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | ||
| 1753 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); | ||
| 1754 | sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); | ||
| 1703 | return ret; | 1755 | return ret; |
| 1704 | 1756 | } | |
| 1705 | return ret; | 1757 | return 0; |
| 1706 | } | 1758 | } |
| 1707 | 1759 | ||
| 1708 | void | 1760 | void |
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 593f298142c1..14504afb044e 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h | |||
| @@ -24,7 +24,7 @@ static inline struct qeth_hdr_tso * | |||
| 24 | qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) | 24 | qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) |
| 25 | { | 25 | { |
| 26 | QETH_DBF_TEXT(trace, 5, "tsoprsk"); | 26 | QETH_DBF_TEXT(trace, 5, "tsoprsk"); |
| 27 | return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso)); | 27 | return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso)); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /** | 30 | /** |
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 293bb2fdb1d5..2f698763ba5d 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c | |||
| @@ -145,8 +145,9 @@ static int opromgetprop(void __user *argp, struct device_node *dp, struct openpr | |||
| 145 | void *pval; | 145 | void *pval; |
| 146 | int len; | 146 | int len; |
| 147 | 147 | ||
| 148 | pval = of_get_property(dp, op->oprom_array, &len); | 148 | if (!dp || |
| 149 | if (!pval || len <= 0 || len > bufsize) | 149 | !(pval = of_get_property(dp, op->oprom_array, &len)) || |
| 150 | len <= 0 || len > bufsize) | ||
| 150 | return copyout(argp, op, sizeof(int)); | 151 | return copyout(argp, op, sizeof(int)); |
| 151 | 152 | ||
| 152 | memcpy(op->oprom_array, pval, len); | 153 | memcpy(op->oprom_array, pval, len); |
| @@ -161,6 +162,8 @@ static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpr | |||
| 161 | struct property *prop; | 162 | struct property *prop; |
| 162 | int len; | 163 | int len; |
| 163 | 164 | ||
| 165 | if (!dp) | ||
| 166 | return copyout(argp, op, sizeof(int)); | ||
| 164 | if (op->oprom_array[0] == '\0') { | 167 | if (op->oprom_array[0] == '\0') { |
| 165 | prop = dp->properties; | 168 | prop = dp->properties; |
| 166 | if (!prop) | 169 | if (!prop) |
| @@ -266,9 +269,13 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp | |||
| 266 | 269 | ||
| 267 | static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) | 270 | static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) |
| 268 | { | 271 | { |
| 272 | phandle ph = 0; | ||
| 273 | |||
| 269 | dp = of_find_node_by_path(op->oprom_array); | 274 | dp = of_find_node_by_path(op->oprom_array); |
| 275 | if (dp) | ||
| 276 | ph = dp->node; | ||
| 270 | data->current_node = dp; | 277 | data->current_node = dp; |
| 271 | *((int *)op->oprom_array) = dp->node; | 278 | *((int *)op->oprom_array) = ph; |
| 272 | op->oprom_size = sizeof(int); | 279 | op->oprom_size = sizeof(int); |
| 273 | 280 | ||
| 274 | return copyout(argp, op, bufsize + sizeof(int)); | 281 | return copyout(argp, op, bufsize + sizeof(int)); |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a8ed5a22009d..3d355d054612 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -466,7 +466,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
| 466 | struct scsi_device *sdev = scmd->device; | 466 | struct scsi_device *sdev = scmd->device; |
| 467 | struct Scsi_Host *shost = sdev->host; | 467 | struct Scsi_Host *shost = sdev->host; |
| 468 | int old_result = scmd->result; | 468 | int old_result = scmd->result; |
| 469 | DECLARE_COMPLETION(done); | 469 | DECLARE_COMPLETION_ONSTACK(done); |
| 470 | unsigned long timeleft; | 470 | unsigned long timeleft; |
| 471 | unsigned long flags; | 471 | unsigned long flags; |
| 472 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; | 472 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; |
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 392bffcf96e8..95738a19cde7 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
| @@ -1621,7 +1621,7 @@ static struct s3c24xx_uart_info s3c2412_uart_inf = { | |||
| 1621 | static int s3c2412_serial_probe(struct platform_device *dev) | 1621 | static int s3c2412_serial_probe(struct platform_device *dev) |
| 1622 | { | 1622 | { |
| 1623 | dbg("s3c2440_serial_probe: dev=%p\n", dev); | 1623 | dbg("s3c2440_serial_probe: dev=%p\n", dev); |
| 1624 | return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); | 1624 | return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); |
| 1625 | } | 1625 | } |
| 1626 | 1626 | ||
| 1627 | static struct platform_driver s3c2412_serial_drv = { | 1627 | static struct platform_driver s3c2412_serial_drv = { |
