diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 08:45:48 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 08:45:48 -0700 |
commit | 95dfec6ae1cb8c03406aac612a5642cbddb676b3 (patch) | |
tree | 978de715f45de94a8e79eb08a08ca5fb9dfd9dea /drivers/s390 | |
parent | ae3a0064e6d69068b1c9fd075095da062430bda9 (diff) | |
parent | 159131149c2f56c1da5ae5e23ab9d5acef4916d1 (diff) | |
download | op-kernel-dev-95dfec6ae1cb8c03406aac612a5642cbddb676b3.zip op-kernel-dev-95dfec6ae1cb8c03406aac612a5642cbddb676b3.tar.gz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (53 commits)
tcp: Overflow bug in Vegas
[IPv4] UFO: prevent generation of chained skb destined to UFO device
iwlwifi: move the selects to the tristate drivers
ipv4: annotate a few functions __init in ipconfig.c
atm: ambassador: vcc_sf semaphore to mutex
MAINTAINERS: The socketcan-core list is subscribers-only.
netfilter: nf_conntrack: padding breaks conntrack hash on ARM
ipv4: Update MTU to all related cache entries in ip_rt_frag_needed()
sch_sfq: use del_timer_sync() in sfq_destroy()
net: Add compat support for getsockopt (MCAST_MSFILTER)
net: Several cleanups for the setsockopt compat support.
ipvs: fix oops in backup for fwmark conn templates
bridge: kernel panic when unloading bridge module
bridge: fix error handling in br_add_if()
netfilter: {nfnetlink,ip,ip6}_queue: fix skb_over_panic when enlarging packets
netfilter: x_tables: fix net namespace leak when reading /proc/net/xxx_tables_names
netfilter: xt_TCPOPTSTRIP: signed tcphoff for ipv6_skip_exthdr() retval
tcp: Limit cwnd growth when deferring for GSO
tcp: Allow send-limited cwnd to grow up to max_burst when gso disabled
[netdrvr] gianfar: Determine TBIPA value dynamically
...
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 96 | ||||
-rw-r--r-- | drivers/s390/net/cu3088.c | 20 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/netiucv.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 50 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 200 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 30 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3.h | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 30 |
9 files changed, 239 insertions, 196 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 85b2e51..26a930e 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -152,44 +152,89 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) return 0; } +static int __get_next_bus_id(const char **buf, char *bus_id) +{ + int rc, len; + char *start, *end; + + start = (char *)*buf; + end = strchr(start, ','); + if (!end) { + /* Last entry. Strip trailing newline, if applicable. */ + end = strchr(start, '\n'); + if (end) + *end = '\0'; + len = strlen(start) + 1; + } else { + len = end - start + 1; + end++; + } + if (len < BUS_ID_SIZE) { + strlcpy(bus_id, start, len); + rc = 0; + } else + rc = -EINVAL; + *buf = end; + return rc; +} + +static int __is_valid_bus_id(char bus_id[BUS_ID_SIZE]) +{ + int cssid, ssid, devno; + + /* Must be of form %x.%x.%04x */ + if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3) + return 0; + return 1; +} + /** - * ccwgroup_create() - create and register a ccw group device + * ccwgroup_create_from_string() - create and register a ccw group device * @root: parent device for the new device * @creator_id: identifier of creating driver * @cdrv: ccw driver of slave devices - * @argc: number of slave devices - * @argv: bus ids of slave devices + * @num_devices: number of slave devices + * @buf: buffer containing comma separated bus ids of slave devices * * Create and register a new ccw group device as a child of @root. Slave - * devices are obtained from the list of bus ids given in @argv[] and must all + * devices are obtained from the list of bus ids given in @buf and must all * belong to @cdrv. * Returns: * %0 on success and an error code on failure. * Context: * non-atomic */ -int ccwgroup_create(struct device *root, unsigned int creator_id, - struct ccw_driver *cdrv, int argc, char *argv[]) +int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, + struct ccw_driver *cdrv, int num_devices, + const char *buf) { struct ccwgroup_device *gdev; - int i; - int rc; + int rc, i; + char tmp_bus_id[BUS_ID_SIZE]; + const char *curr_buf; - if (argc > 256) /* disallow dumb users */ - return -EINVAL; - - gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL); + gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), + GFP_KERNEL); if (!gdev) return -ENOMEM; atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); - for (i = 0; i < argc; i++) { - gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); - - /* all devices have to be of the same type in - * order to be grouped */ + curr_buf = buf; + for (i = 0; i < num_devices && curr_buf; i++) { + rc = __get_next_bus_id(&curr_buf, tmp_bus_id); + if (rc != 0) + goto error; + if (!__is_valid_bus_id(tmp_bus_id)) { + rc = -EINVAL; + goto error; + } + gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id); + /* + * All devices have to be of the same type in + * order to be grouped. + */ if (!gdev->cdev[i] || gdev->cdev[i]->id.driver_info != gdev->cdev[0]->id.driver_info) { @@ -203,9 +248,18 @@ int ccwgroup_create(struct device *root, unsigned int creator_id, } dev_set_drvdata(&gdev->cdev[i]->dev, gdev); } - + /* Check for sufficient number of bus ids. */ + if (i < num_devices && !curr_buf) { + rc = -EINVAL; + goto error; + } + /* Check for trailing stuff. */ + if (i == num_devices && strlen(curr_buf) > 0) { + rc = -EINVAL; + goto error; + } gdev->creator_id = creator_id; - gdev->count = argc; + gdev->count = num_devices; gdev->dev.bus = &ccwgroup_bus_type; gdev->dev.parent = root; gdev->dev.release = ccwgroup_release; @@ -233,7 +287,7 @@ int ccwgroup_create(struct device *root, unsigned int creator_id, device_remove_file(&gdev->dev, &dev_attr_ungroup); device_unregister(&gdev->dev); error: - for (i = 0; i < argc; i++) + for (i = 0; i < num_devices; i++) if (gdev->cdev[i]) { if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) dev_set_drvdata(&gdev->cdev[i]->dev, NULL); @@ -243,6 +297,7 @@ error: put_device(&gdev->dev); return rc; } +EXPORT_SYMBOL(ccwgroup_create_from_string); static int __init init_ccwgroup (void) @@ -521,6 +576,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev) MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ccwgroup_driver_register); EXPORT_SYMBOL(ccwgroup_driver_unregister); -EXPORT_SYMBOL(ccwgroup_create); EXPORT_SYMBOL(ccwgroup_probe_ccwdev); EXPORT_SYMBOL(ccwgroup_remove_ccwdev); diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 76728ae..8e76973 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c @@ -62,30 +62,14 @@ static struct device *cu3088_root_dev; static ssize_t group_write(struct device_driver *drv, const char *buf, size_t count) { - const char *start, *end; - char bus_ids[2][BUS_ID_SIZE], *argv[2]; - int i; int ret; struct ccwgroup_driver *cdrv; cdrv = to_ccwgroupdrv(drv); if (!cdrv) return -EINVAL; - start = buf; - for (i=0; i<2; i++) { - static const char delim[] = {',', '\n'}; - int len; - - if (!(end = strchr(start, delim[i]))) - return -EINVAL; - len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1); - strlcpy (bus_ids[i], start, len); - argv[i] = bus_ids[i]; - start = end + 1; - } - - ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id, - &cu3088_driver, 2, argv); + ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id, + &cu3088_driver, 2, buf); return (ret == 0) ? count : ret; } diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index f51ed99..dd22f4b 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1793,7 +1793,8 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len) skb->protocol = card->lan_type_trans(skb, card->dev); card->stats.rx_bytes += skb_len; card->stats.rx_packets++; - *((__u32 *)skb->cb) = ++card->pkt_seq; + if (skb->protocol == htons(ETH_P_802_2)) + *((__u32 *)skb->cb) = ++card->pkt_seq; netif_rx(skb); } diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 8f876f6..e4ba6a0 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1313,8 +1313,6 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) * and throw away packet. */ if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) { - if (!in_atomic()) - fsm_event(privptr->fsm, DEV_EVENT_START, dev); dev_kfree_skb(skb); privptr->stats.tx_dropped++; privptr->stats.tx_errors++; @@ -2147,6 +2145,7 @@ static int __init netiucv_init(void) if (rc) goto out_dbf; IUCV_DBF_TEXT(trace, 3, __func__); + netiucv_driver.groups = netiucv_drv_attr_groups; rc = driver_register(&netiucv_driver); if (rc) { PRINT_ERR("NETIUCV: failed to register driver.\n"); diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 66f4f12..699ac11 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -72,22 +72,7 @@ struct qeth_dbf_info { debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text) #define QETH_DBF_TEXT_(name, level, text...) \ - do { \ - if (qeth_dbf_passes(qeth_dbf[QETH_DBF_##name].id, level)) { \ - char *dbf_txt_buf = \ - get_cpu_var(QETH_DBF_TXT_BUF); \ - sprintf(dbf_txt_buf, text); \ - debug_text_event(qeth_dbf[QETH_DBF_##name].id, \ - level, dbf_txt_buf); \ - put_cpu_var(QETH_DBF_TXT_BUF); \ - } \ - } while (0) - -/* Allow to sort out low debug levels early to avoid wasted sprints */ -static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level) -{ - return (level <= dbf_grp->level); -} + qeth_dbf_longtext(QETH_DBF_##name, level, text) /** * some more debug stuff @@ -773,27 +758,6 @@ static inline int qeth_get_micros(void) return (int) (get_clock() >> 12); } -static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, - int size) -{ - void *hdr; - - hdr = (void *) skb_push(skb, size); - /* - * sanity check, the Linux memory allocation scheme should - * never present us cases like this one (the qdio header size plus - * the first 40 bytes of the paket cross a 4k boundary) - */ - if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) != - (((unsigned long) hdr + size + - QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { - PRINT_ERR("Misaligned packet on interface %s. Discarded.", - QETH_CARD_IFNAME(card)); - return NULL; - } - return hdr; -} - static inline int qeth_get_ip_version(struct sk_buff *skb) { switch (skb->protocol) { @@ -806,6 +770,12 @@ static inline int qeth_get_ip_version(struct sk_buff *skb) } } +static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, + struct qeth_buffer_pool_entry *entry) +{ + list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); +} + struct qeth_eddp_context; extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; @@ -843,8 +813,6 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *, int qeth_query_setadapterparms(struct qeth_card *); int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int, unsigned int, const char *); -void qeth_put_buffer_pool_entry(struct qeth_card *, - struct qeth_buffer_pool_entry *); void qeth_queue_input_buffer(struct qeth_card *, int); struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, struct qdio_buffer *, struct qdio_buffer_element **, int *, @@ -880,8 +848,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, void *reply_param); int qeth_get_cast_type(struct qeth_card *, struct sk_buff *); int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); -struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *, - struct qeth_hdr **); int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, struct sk_buff *, struct qeth_hdr *, int, @@ -894,6 +860,8 @@ void qeth_core_get_ethtool_stats(struct net_device *, struct ethtool_stats *, u64 *); void qeth_core_get_strings(struct net_device *, u32, u8 *); void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); +void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...); +int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); /* exports for OSN */ int qeth_osn_assist(struct net_device *, void *, int); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 055f5c3..436bf1f 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -26,9 +26,6 @@ #include "qeth_core.h" #include "qeth_core_offl.h" -static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf); -#define QETH_DBF_TXT_BUF qeth_core_dbf_txt_buf - struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = { /* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */ /* N P A M L V H */ @@ -2255,14 +2252,6 @@ void qeth_print_status_message(struct qeth_card *card) } EXPORT_SYMBOL_GPL(qeth_print_status_message); -void qeth_put_buffer_pool_entry(struct qeth_card *card, - struct qeth_buffer_pool_entry *entry) -{ - QETH_DBF_TEXT(TRACE, 6, "ptbfplen"); - list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); -} -EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry); - static void qeth_initialize_working_pool_list(struct qeth_card *card) { struct qeth_buffer_pool_entry *entry; @@ -2603,7 +2592,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) int rc; int newcount = 0; - QETH_DBF_TEXT(TRACE, 6, "queinbuf"); count = (index < queue->next_buf_to_init)? card->qdio.in_buf_pool.buf_count - (queue->next_buf_to_init - index) : @@ -2792,8 +2780,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, int i; unsigned int qdio_flags; - QETH_DBF_TEXT(TRACE, 6, "flushbuf"); - for (i = index; i < index + count; ++i) { buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; buf->buffer->element[buf->next_element_to_fill - 1].flags |= @@ -3037,49 +3023,6 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(qeth_get_priority_queue); -static void __qeth_free_new_skb(struct sk_buff *orig_skb, - struct sk_buff *new_skb) -{ - if (orig_skb != new_skb) - dev_kfree_skb_any(new_skb); -} - -static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card, - struct sk_buff *skb, int size) -{ - struct sk_buff *new_skb = skb; - - if (skb_headroom(skb) >= size) - return skb; - new_skb = skb_realloc_headroom(skb, size); - if (!new_skb) - PRINT_ERR("Could not realloc headroom for qeth_hdr " - "on interface %s", QETH_CARD_IFNAME(card)); - return new_skb; -} - -struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr **hdr) -{ - struct sk_buff *new_skb; - - QETH_DBF_TEXT(TRACE, 6, "prepskb"); - - new_skb = qeth_realloc_headroom(card, skb, - sizeof(struct qeth_hdr)); - if (!new_skb) - return NULL; - - *hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb, - sizeof(struct qeth_hdr))); - if (*hdr == NULL) { - __qeth_free_new_skb(skb, new_skb); - return NULL; - } - return new_skb; -} -EXPORT_SYMBOL_GPL(qeth_prepare_skb); - int qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb, int elems) { @@ -3100,8 +3043,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr, } EXPORT_SYMBOL_GPL(qeth_get_elements_no); -static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, - int is_tso, int *next_element_to_fill) +static inline void __qeth_fill_buffer(struct sk_buff *skb, + struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill) { int length = skb->len; int length_here; @@ -3143,15 +3086,13 @@ static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, *next_element_to_fill = element; } -static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, +static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf, struct sk_buff *skb) { struct qdio_buffer *buffer; struct qeth_hdr_tso *hdr; int flush_cnt = 0, hdr_len, large_send = 0; - QETH_DBF_TEXT(TRACE, 6, "qdfillbf"); - buffer = buf->buffer; atomic_inc(&skb->users); skb_queue_tail(&buf->skb_list, skb); @@ -3210,8 +3151,6 @@ int qeth_do_send_packet_fast(struct qeth_card *card, int flush_cnt = 0; int index; - QETH_DBF_TEXT(TRACE, 6, "dosndpfa"); - /* spin until we get the queue ... */ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); @@ -3263,8 +3202,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, int tmp; int rc = 0; - QETH_DBF_TEXT(TRACE, 6, "dosndpkt"); - /* spin until we get the queue ... */ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); @@ -3827,27 +3764,8 @@ static struct ccw_driver qeth_ccw_driver = { static int qeth_core_driver_group(const char *buf, struct device *root_dev, unsigned long driver_id) { - const char *start, *end; - char bus_ids[3][BUS_ID_SIZE], *argv[3]; - int i; - - start = buf; - for (i = 0; i < 3; i++) { - static const char delim[] = { ',', ',', '\n' }; - int len; - - end = strchr(start, delim[i]); - if (!end) - return -EINVAL; - len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start); - strncpy(bus_ids[i], start, len); - bus_ids[i][len] = '\0'; - start = end + 1; - argv[i] = bus_ids[i]; - } - - return (ccwgroup_create(root_dev, driver_id, - &qeth_ccw_driver, 3, argv)); + return ccwgroup_create_from_string(root_dev, driver_id, + &qeth_ccw_driver, 3, buf); } int qeth_core_hardsetup_card(struct qeth_card *card) @@ -3885,8 +3803,9 @@ retry: QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); return rc; } - - mpno = QETH_MAX_PORTNO; + mpno = qdio_get_ssqd_pct(CARD_DDEV(card)); + if (mpno) + mpno = min(mpno - 1, QETH_MAX_PORTNO); if (card->info.portno > mpno) { PRINT_ERR("Device %s does not offer port number %d \n.", CARD_BUS_ID(card), card->info.portno); @@ -3980,7 +3899,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, int use_rx_sg = 0; int frag = 0; - QETH_DBF_TEXT(TRACE, 6, "nextskb"); /* qeth_hdr must not cross element boundaries */ if (element->length < offset + sizeof(struct qeth_hdr)) { if (qeth_is_last_sbale(element)) @@ -4086,6 +4004,18 @@ static void qeth_unregister_dbf_views(void) } } +void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...) +{ + char dbf_txt_buf[32]; + + if (level > (qeth_dbf[dbf_nix].id)->level) + return; + snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text); + debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf); + +} +EXPORT_SYMBOL_GPL(qeth_dbf_longtext); + static int qeth_register_dbf_views(void) { int ret; @@ -4433,6 +4363,96 @@ void qeth_core_get_drvinfo(struct net_device *dev, } EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); +int qeth_core_ethtool_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct qeth_card *card = netdev_priv(netdev); + enum qeth_link_types link_type; + + if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan)) + link_type = QETH_LINK_TYPE_10GBIT_ETH; + else + link_type = card->info.link_type; + + ecmd->transceiver = XCVR_INTERNAL; + ecmd->supported = SUPPORTED_Autoneg; + ecmd->advertising = ADVERTISED_Autoneg; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_ENABLE; + + switch (link_type) { + case QETH_LINK_TYPE_FAST_ETH: + case QETH_LINK_TYPE_LANE_ETH100: + ecmd->supported |= SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_TP; + ecmd->advertising |= ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_TP; + ecmd->speed = SPEED_100; + ecmd->port = PORT_TP; + break; + + case QETH_LINK_TYPE_GBIT_ETH: + case QETH_LINK_TYPE_LANE_ETH1000: + ecmd->supported |= SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE; + ecmd->speed = SPEED_1000; + ecmd->port = PORT_FIBRE; + break; + + case QETH_LINK_TYPE_10GBIT_ETH: + ecmd->supported |= SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_10000baseT_Full | + ADVERTISED_FIBRE; + ecmd->speed = SPEED_10000; + ecmd->port = PORT_FIBRE; + break; + + default: + ecmd->supported |= SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_TP; + ecmd->advertising |= ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_TP; + ecmd->speed = SPEED_10; + ecmd->port = PORT_TP; + } + + return 0; +} +EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings); + static int __init qeth_core_init(void) { int rc; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 3921d1631..86ec50d 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -22,9 +22,6 @@ #include "qeth_core.h" #include "qeth_core_offl.h" -#define QETH_DBF_TXT_BUF qeth_l2_dbf_txt_buf -static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf); - static int qeth_l2_set_offline(struct ccwgroup_device *); static int qeth_l2_stop(struct net_device *); static int qeth_l2_send_delmac(struct qeth_card *, __u8 *); @@ -635,8 +632,6 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; - QETH_DBF_TEXT(TRACE, 6, "l2xmit"); - if ((card->state != CARD_STATE_UP) || !card->lan_online) { card->stats.tx_carrier_errors++; goto tx_drop; @@ -658,9 +653,12 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (card->info.type == QETH_CARD_TYPE_OSN) hdr = (struct qeth_hdr *)skb->data; else { - new_skb = qeth_prepare_skb(card, skb, &hdr); + /* create a clone with writeable headroom */ + new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr)); if (!new_skb) goto tx_drop; + hdr = (struct qeth_hdr *)skb_push(new_skb, + sizeof(struct qeth_hdr)); qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type); } @@ -747,7 +745,6 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev, int index; int i; - QETH_DBF_TEXT(TRACE, 6, "qdinput"); card = (struct qeth_card *) card_ptr; net_dev = card->dev; if (card->options.performance_stats) { @@ -852,6 +849,22 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) return; } +static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data) +{ + struct qeth_card *card = netdev_priv(dev); + + if (data) { + if (card->options.large_send == QETH_LARGE_SEND_NO) { + card->options.large_send = QETH_LARGE_SEND_EDDP; + dev->features |= NETIF_F_TSO; + } + } else { + dev->features &= ~NETIF_F_TSO; + card->options.large_send = QETH_LARGE_SEND_NO; + } + return 0; +} + static struct ethtool_ops qeth_l2_ethtool_ops = { .get_link = ethtool_op_get_link, .get_tx_csum = ethtool_op_get_tx_csum, @@ -859,11 +872,12 @@ static struct ethtool_ops qeth_l2_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, + .set_tso = qeth_l2_ethtool_set_tso, .get_strings = qeth_core_get_strings, .get_ethtool_stats = qeth_core_get_ethtool_stats, .get_stats_count = qeth_core_get_stats_count, .get_drvinfo = qeth_core_get_drvinfo, + .get_settings = qeth_core_ethtool_get_settings, }; static struct ethtool_ops qeth_l2_osn_ops = { diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 1be3535..9f143c8 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h @@ -13,9 +13,6 @@ #include "qeth_core.h" -#define QETH_DBF_TXT_BUF qeth_l3_dbf_txt_buf -DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf); - struct qeth_ipaddr { struct list_head entry; enum qeth_ip_types type; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e1bfe56..94a8ead 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -28,8 +28,6 @@ #include "qeth_l3.h" #include "qeth_core_offl.h" -DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf); - static int qeth_l3_set_offline(struct ccwgroup_device *); static int qeth_l3_recover(void *); static int qeth_l3_stop(struct net_device *); @@ -2093,6 +2091,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) (card->state == CARD_STATE_UP)) { if (recovery_mode) qeth_l3_stop(card->dev); + else { + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); + } if (!card->use_hard_stop) { rc = qeth_send_stoplan(card); if (rc) @@ -2559,8 +2562,6 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int ipv, int cast_type) { - QETH_DBF_TEXT(TRACE, 6, "fillhdr"); - memset(hdr, 0, sizeof(struct qeth_hdr)); hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; hdr->hdr.l3.ext_flags = 0; @@ -2570,9 +2571,10 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, * v6 uses passthrough, v4 sets the tag in the QDIO header. */ if (card->vlangrp && vlan_tx_tag_present(skb)) { - hdr->hdr.l3.ext_flags = (ipv == 4) ? - QETH_HDR_EXT_VLAN_FRAME : - QETH_HDR_EXT_INCLUDE_VLAN_TAG; + if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD)) + hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME; + else + hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG; hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb); } @@ -2638,8 +2640,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; - QETH_DBF_TEXT(TRACE, 6, "l3xmit"); - if ((card->info.type == QETH_CARD_TYPE_IQD) && (skb->protocol != htons(ETH_P_IPV6)) && (skb->protocol != htons(ETH_P_IP))) @@ -2890,6 +2890,7 @@ static struct ethtool_ops qeth_l3_ethtool_ops = { .get_ethtool_stats = qeth_core_get_ethtool_stats, .get_stats_count = qeth_core_get_stats_count, .get_drvinfo = qeth_core_get_drvinfo, + .get_settings = qeth_core_ethtool_get_settings, }; /* @@ -2982,7 +2983,6 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev, int index; int i; - QETH_DBF_TEXT(TRACE, 6, "qdinput"); card = (struct qeth_card *) card_ptr; net_dev = card->dev; if (card->options.performance_stats) { @@ -3140,9 +3140,15 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) netif_carrier_on(card->dev); qeth_set_allowed_threads(card, 0xffffffff, 0); - if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) { + if (recover_flag == CARD_STATE_RECOVER) { + if (recovery_mode) qeth_l3_open(card->dev); - qeth_l3_set_multicast_list(card->dev); + else { + rtnl_lock(); + dev_open(card->dev); + rtnl_unlock(); + } + qeth_l3_set_multicast_list(card->dev); } /* let user_space know that device is online */ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |