X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fnet%2Fqeth_sys.c;h=5836737ac58f26157f8d21d54c9ec1bd0723e07b;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=910c5f5666b67d7b0a125c1676f1af5f9ef9b499;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 910c5f566..5836737ac 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.32 $) + * linux/drivers/s390/net/qeth_sys.c * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -8,7 +8,7 @@ * Copyright 2000,2003 IBM Corporation * * Author(s): Thomas Spatzier - * Frank Pavlic + * Frank Pavlic * */ #include @@ -20,8 +20,6 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.32 $"; - /*****************************************************************************/ /* */ /* /sys-fs stuff UNDER DEVELOPMENT !!! */ @@ -30,7 +28,7 @@ const char *VERSION_QETH_SYS_C = "$Revision: 1.32 $"; //low/high watermark static ssize_t -qeth_dev_state_show(struct device *dev, char *buf) +qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) @@ -58,7 +56,7 @@ qeth_dev_state_show(struct device *dev, char *buf) static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL); static ssize_t -qeth_dev_chpid_show(struct device *dev, char *buf) +qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) @@ -70,19 +68,18 @@ qeth_dev_chpid_show(struct device *dev, char *buf) static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL); static ssize_t -qeth_dev_if_name_show(struct device *dev, char *buf) +qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; - - return sprintf(buf, "%s\n", card->info.if_name); + return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card)); } static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL); static ssize_t -qeth_dev_card_type_show(struct device *dev, char *buf) +qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) @@ -94,7 +91,7 @@ qeth_dev_card_type_show(struct device *dev, char *buf) static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL); static ssize_t -qeth_dev_portno_show(struct device *dev, char *buf) +qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) @@ -104,7 +101,7 @@ qeth_dev_portno_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_portno_store(struct device *dev, const char *buf, size_t count) +qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -118,7 +115,7 @@ qeth_dev_portno_store(struct device *dev, const char *buf, size_t count) return -EPERM; portno = simple_strtoul(buf, &tmp, 16); - if ((portno < 0) || (portno > MAX_PORTNO)){ + if (portno > MAX_PORTNO){ PRINT_WARN("portno 0x%X is out of range\n", portno); return -EINVAL; } @@ -130,7 +127,7 @@ qeth_dev_portno_store(struct device *dev, const char *buf, size_t count) static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store); static ssize_t -qeth_dev_portname_show(struct device *dev, char *buf) +qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; char portname[9] = {0, }; @@ -147,7 +144,7 @@ qeth_dev_portname_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_portname_store(struct device *dev, const char *buf, size_t count) +qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -161,7 +158,7 @@ qeth_dev_portname_store(struct device *dev, const char *buf, size_t count) return -EPERM; tmp = strsep((char **) &buf, "\n"); - if ((strlen(tmp) > 8) || (strlen(tmp) < 2)) + if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) return -EINVAL; card->info.portname[0] = strlen(tmp); @@ -178,7 +175,7 @@ static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show, qeth_dev_portname_store); static ssize_t -qeth_dev_checksum_show(struct device *dev, char *buf) +qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -189,7 +186,7 @@ qeth_dev_checksum_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_checksum_store(struct device *dev, const char *buf, size_t count) +qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -219,7 +216,7 @@ static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show, qeth_dev_checksum_store); static ssize_t -qeth_dev_prioqing_show(struct device *dev, char *buf) +qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -238,7 +235,7 @@ qeth_dev_prioqing_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count) +qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -250,6 +247,16 @@ qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count) (card->state != CARD_STATE_RECOVER)) return -EPERM; + /* check if 1920 devices are supported , + * if though we have to permit priority queueing + */ + if (card->qdio.no_out_queues == 1) { + PRINT_WARN("Priority queueing disabled due " + "to hardware limitations!\n"); + card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; + return -EPERM; + } + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "prio_queueing_prec")) card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC; @@ -281,7 +288,7 @@ static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show, qeth_dev_prioqing_store); static ssize_t -qeth_dev_bufcnt_show(struct device *dev, char *buf) +qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -292,7 +299,7 @@ qeth_dev_bufcnt_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_bufcnt_store(struct device *dev, const char *buf, size_t count) +qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -351,7 +358,7 @@ qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, } static ssize_t -qeth_dev_route4_show(struct device *dev, char *buf) +qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -401,7 +408,7 @@ qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route, } static ssize_t -qeth_dev_route4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -416,7 +423,7 @@ static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store); #ifdef CONFIG_QETH_IPV6 static ssize_t -qeth_dev_route6_show(struct device *dev, char *buf) +qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -430,7 +437,7 @@ qeth_dev_route6_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_route6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -440,7 +447,7 @@ qeth_dev_route6_store(struct device *dev, const char *buf, size_t count) if (!qeth_is_supported(card, IPA_IPV6)){ PRINT_WARN("IPv6 not supported for interface %s.\n" "Routing status no changed.\n", - card->info.if_name); + QETH_CARD_IFNAME(card)); return -ENOTSUPP; } @@ -452,7 +459,7 @@ static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store); #endif static ssize_t -qeth_dev_add_hhlen_show(struct device *dev, char *buf) +qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -463,7 +470,7 @@ qeth_dev_add_hhlen_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_add_hhlen_store(struct device *dev, const char *buf, size_t count) +qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -476,7 +483,7 @@ qeth_dev_add_hhlen_store(struct device *dev, const char *buf, size_t count) (card->state != CARD_STATE_RECOVER)) return -EPERM; - i = simple_strtoul(buf, &tmp, 16); + i = simple_strtoul(buf, &tmp, 10); if ((i < 0) || (i > MAX_ADD_HHLEN)) { PRINT_WARN("add_hhlen out of range\n"); return -EINVAL; @@ -490,7 +497,7 @@ static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show, qeth_dev_add_hhlen_store); static ssize_t -qeth_dev_fake_ll_show(struct device *dev, char *buf) +qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -501,7 +508,7 @@ qeth_dev_fake_ll_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_fake_ll_store(struct device *dev, const char *buf, size_t count) +qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -515,12 +522,11 @@ qeth_dev_fake_ll_store(struct device *dev, const char *buf, size_t count) return -EPERM; i = simple_strtoul(buf, &tmp, 16); - if ((i == 0) || (i == 1)) - card->options.fake_ll = i; - else { + if ((i != 0) && (i != 1)) { PRINT_WARN("fake_ll: write 0 or 1 to this file!\n"); return -EINVAL; } + card->options.fake_ll = i; return count; } @@ -528,7 +534,7 @@ static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show, qeth_dev_fake_ll_store); static ssize_t -qeth_dev_fake_broadcast_show(struct device *dev, char *buf) +qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -539,7 +545,7 @@ qeth_dev_fake_broadcast_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_fake_broadcast_store(struct device *dev, const char *buf, size_t count) +qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -566,7 +572,7 @@ static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show, qeth_dev_fake_broadcast_store); static ssize_t -qeth_dev_recover_store(struct device *dev, const char *buf, size_t count) +qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -588,7 +594,7 @@ qeth_dev_recover_store(struct device *dev, const char *buf, size_t count) static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store); static ssize_t -qeth_dev_broadcast_mode_show(struct device *dev, char *buf) +qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -605,7 +611,7 @@ qeth_dev_broadcast_mode_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_broadcast_mode_store(struct device *dev, const char *buf, size_t count) +qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -643,7 +649,7 @@ static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show, qeth_dev_broadcast_mode_store); static ssize_t -qeth_dev_canonical_macaddr_show(struct device *dev, char *buf) +qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -659,7 +665,7 @@ qeth_dev_canonical_macaddr_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf, +qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -694,6 +700,253 @@ qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf, static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show, qeth_dev_canonical_macaddr_store); +static ssize_t +qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.layer2 ? 1:0); +} + +static ssize_t +qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return -EINVAL; + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); + return -EPERM; + } + + if (((card->state != CARD_STATE_DOWN) && + (card->state != CARD_STATE_RECOVER))) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if ((i == 0) || (i == 1)) + card->options.layer2 = i; + else { + PRINT_WARN("layer2: write 0 or 1 to this file!\n"); + return -EINVAL; + } + return count; +} + +static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, + qeth_dev_layer2_store); + +static ssize_t +qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); +} + +static ssize_t +qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return -EINVAL; + + i = simple_strtoul(buf, &tmp, 16); + if ((i == 0) || (i == 1)) { + if (i == card->options.performance_stats) + return count; + card->options.performance_stats = i; + if (i == 0) + memset(&card->perf_stats, 0, + sizeof(struct qeth_perf_stats)); + card->perf_stats.initial_rx_packets = card->stats.rx_packets; + card->perf_stats.initial_tx_packets = card->stats.tx_packets; + } else { + PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); + return -EINVAL; + } + return count; +} + +static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, + qeth_dev_performance_stats_store); + +static ssize_t +qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + switch (card->options.large_send) { + case QETH_LARGE_SEND_NO: + return sprintf(buf, "%s\n", "no"); + case QETH_LARGE_SEND_EDDP: + return sprintf(buf, "%s\n", "EDDP"); + case QETH_LARGE_SEND_TSO: + return sprintf(buf, "%s\n", "TSO"); + default: + return sprintf(buf, "%s\n", "N/A"); + } +} + +static ssize_t +qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + enum qeth_large_send_types type; + int rc = 0; + char *tmp; + + if (!card) + return -EINVAL; + tmp = strsep((char **) &buf, "\n"); + if (!strcmp(tmp, "no")){ + type = QETH_LARGE_SEND_NO; + } else if (!strcmp(tmp, "EDDP")) { + type = QETH_LARGE_SEND_EDDP; + } else if (!strcmp(tmp, "TSO")) { + type = QETH_LARGE_SEND_TSO; + } else { + PRINT_WARN("large_send: invalid mode %s!\n", tmp); + return -EINVAL; + } + if (card->options.large_send == type) + return count; + if ((rc = qeth_set_large_send(card, type))) + return rc; + return count; +} + +static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show, + qeth_dev_large_send_store); + +static ssize_t +qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value ) +{ + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", value); +} + +static ssize_t +qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count, + int *value, int max_value) +{ + char *tmp; + int i; + + if (!card) + return -EINVAL; + + if ((card->state != CARD_STATE_DOWN) && + (card->state != CARD_STATE_RECOVER)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 10); + if (i <= max_value) { + *value = i; + } else { + PRINT_WARN("blkt total time: write values between" + " 0 and %d to this file!\n", max_value); + return -EINVAL; + } + return count; +} + +static ssize_t +qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total); +} + + +static ssize_t +qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_store(card, buf, count, + &card->info.blkt.time_total,1000); +} + + + +static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show, + qeth_dev_blkt_total_store); + +static ssize_t +qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet); +} + + +static ssize_t +qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_store(card, buf, count, + &card->info.blkt.inter_packet,100); +} + +static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show, + qeth_dev_blkt_inter_store); + +static ssize_t +qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_show(buf, card, + card->info.blkt.inter_packet_jumbo); +} + + +static ssize_t +qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + + return qeth_dev_blkt_store(card, buf, count, + &card->info.blkt.inter_packet_jumbo,100); +} + +static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show, + qeth_dev_blkt_inter_jumbo_store); + +static struct device_attribute * qeth_blkt_device_attrs[] = { + &dev_attr_total, + &dev_attr_inter, + &dev_attr_inter_jumbo, + NULL, +}; + +static struct attribute_group qeth_device_blkt_group = { + .name = "blkt", + .attrs = (struct attribute **)qeth_blkt_device_attrs, +}; + static struct device_attribute * qeth_device_attrs[] = { &dev_attr_state, &dev_attr_chpid, @@ -714,6 +967,9 @@ static struct device_attribute * qeth_device_attrs[] = { &dev_attr_recover, &dev_attr_broadcast_mode, &dev_attr_canonical_macaddr, + &dev_attr_layer2, + &dev_attr_large_send, + &dev_attr_performance_stats, NULL, }; @@ -721,6 +977,19 @@ static struct attribute_group qeth_device_attr_group = { .attrs = (struct attribute **)qeth_device_attrs, }; +static struct device_attribute * qeth_osn_device_attrs[] = { + &dev_attr_state, + &dev_attr_chpid, + &dev_attr_if_name, + &dev_attr_card_type, + &dev_attr_buffer_count, + &dev_attr_recover, + NULL, +}; + +static struct attribute_group qeth_osn_device_attr_group = { + .attrs = (struct attribute **)qeth_osn_device_attrs, +}; #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ struct device_attribute dev_attr_##_id = { \ @@ -729,19 +998,30 @@ struct device_attribute dev_attr_##_id = { \ .store = _store, \ }; +int +qeth_check_layer2(struct qeth_card *card) +{ + if (card->options.layer2) + return -EPERM; + return 0; +} + + static ssize_t -qeth_dev_ipato_enable_show(struct device *dev, char *buf) +qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; return sprintf(buf, "%i\n", card->ipato.enabled? 1:0); } static ssize_t -qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -753,6 +1033,9 @@ qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count) (card->state != CARD_STATE_RECOVER)) return -EPERM; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.enabled = (card->ipato.enabled)? 0 : 1; @@ -773,18 +1056,21 @@ static QETH_DEVICE_ATTR(ipato_enable, enable, 0644, qeth_dev_ipato_enable_store); static ssize_t -qeth_dev_ipato_invert4_show(struct device *dev, char *buf) +qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return sprintf(buf, "%i\n", card->ipato.invert4? 1:0); } static ssize_t -qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -792,6 +1078,9 @@ qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; @@ -817,24 +1106,37 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, { struct qeth_ipato_entry *ipatoe; unsigned long flags; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + /* add strlen for "/\n" */ + entry_len += (proto == QETH_PROT_IPV4)? 5 : 6; spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipatoe, &card->ipato.entries, entry){ if (ipatoe->proto != proto) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str); - i += sprintf(buf + i, "%s/%i\n", addr_str, ipatoe->mask_bits); + i += snprintf(buf + i, PAGE_SIZE - i, + "%s/%i\n", addr_str, ipatoe->mask_bits); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } static ssize_t -qeth_dev_ipato_add4_show(struct device *dev, char *buf) +qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -850,12 +1152,12 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, { const char *start, *end; char *tmp; - char buffer[49] = {0, }; + char buffer[40] = {0, }; start = buf; /* get address string */ end = strchr(start, '/'); - if (!end){ + if (!end || (end - start >= 40)){ PRINT_WARN("Invalid format for ipato_addx/delx. " "Use /\n"); return -EINVAL; @@ -867,7 +1169,12 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, } start = end + 1; *mask_bits = simple_strtoul(start, &tmp, 10); - + if (!strlen(start) || + (tmp == start) || + (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { + PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); + return -EINVAL; + } return 0; } @@ -880,14 +1187,15 @@ qeth_dev_ipato_add_store(const char *buf, size_t count, int mask_bits; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; - if (!(ipatoe = kmalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ + if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ PRINT_WARN("No memory to allocate ipato entry\n"); return -ENOMEM; } - memset(ipatoe, 0, sizeof(struct qeth_ipato_entry)); ipatoe->proto = proto; memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16); ipatoe->mask_bits = mask_bits; @@ -901,7 +1209,7 @@ qeth_dev_ipato_add_store(const char *buf, size_t count, } static ssize_t -qeth_dev_ipato_add4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -923,6 +1231,8 @@ qeth_dev_ipato_del_store(const char *buf, size_t count, int mask_bits; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; @@ -932,7 +1242,7 @@ qeth_dev_ipato_del_store(const char *buf, size_t count, } static ssize_t -qeth_dev_ipato_del4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -947,18 +1257,21 @@ static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL, #ifdef CONFIG_QETH_IPV6 static ssize_t -qeth_dev_ipato_invert6_show(struct device *dev, char *buf) +qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return sprintf(buf, "%i\n", card->ipato.invert6? 1:0); } static ssize_t -qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; char *tmp; @@ -966,6 +1279,9 @@ qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.invert6 = (card->ipato.invert6)? 0 : 1; @@ -987,7 +1303,7 @@ static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644, static ssize_t -qeth_dev_ipato_add6_show(struct device *dev, char *buf) +qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -998,7 +1314,7 @@ qeth_dev_ipato_add6_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_ipato_add6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1013,7 +1329,7 @@ static QETH_DEVICE_ATTR(ipato_add6, add6, 0644, qeth_dev_ipato_add6_store); static ssize_t -qeth_dev_ipato_del6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1050,27 +1366,38 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { struct qeth_ipaddr *ipaddr; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ unsigned long flags; int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + entry_len += 2; /* \n + terminator */ spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipaddr, &card->ip_list, entry){ if (ipaddr->proto != proto) continue; if (ipaddr->type != QETH_IP_TYPE_VIPA) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); - i += sprintf(buf + i, "%s\n", addr_str); + i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } static ssize_t -qeth_dev_vipa_add4_show(struct device *dev, char *buf) +qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -1098,6 +1425,8 @@ qeth_dev_vipa_add_store(const char *buf, size_t count, u8 addr[16] = {0, }; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_vipae(buf, proto, addr))) return rc; @@ -1108,7 +1437,7 @@ qeth_dev_vipa_add_store(const char *buf, size_t count, } static ssize_t -qeth_dev_vipa_add4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1129,6 +1458,8 @@ qeth_dev_vipa_del_store(const char *buf, size_t count, u8 addr[16]; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_vipae(buf, proto, addr))) return rc; @@ -1138,7 +1469,7 @@ qeth_dev_vipa_del_store(const char *buf, size_t count, } static ssize_t -qeth_dev_vipa_del4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1153,7 +1484,7 @@ static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL, #ifdef CONFIG_QETH_IPV6 static ssize_t -qeth_dev_vipa_add6_show(struct device *dev, char *buf) +qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -1164,7 +1495,7 @@ qeth_dev_vipa_add6_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_vipa_add6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1179,13 +1510,16 @@ static QETH_DEVICE_ATTR(vipa_add6, add6, 0644, qeth_dev_vipa_add6_store); static ssize_t -qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6); } @@ -1213,27 +1547,38 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { struct qeth_ipaddr *ipaddr; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ unsigned long flags; int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + entry_len += 2; /* \n + terminator */ spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipaddr, &card->ip_list, entry){ if (ipaddr->proto != proto) continue; if (ipaddr->type != QETH_IP_TYPE_RXIP) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); - i += sprintf(buf + i, "%s\n", addr_str); + i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } static ssize_t -qeth_dev_rxip_add4_show(struct device *dev, char *buf) +qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -1261,6 +1606,8 @@ qeth_dev_rxip_add_store(const char *buf, size_t count, u8 addr[16] = {0, }; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_rxipe(buf, proto, addr))) return rc; @@ -1271,7 +1618,7 @@ qeth_dev_rxip_add_store(const char *buf, size_t count, } static ssize_t -qeth_dev_rxip_add4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1292,6 +1639,8 @@ qeth_dev_rxip_del_store(const char *buf, size_t count, u8 addr[16]; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_rxipe(buf, proto, addr))) return rc; @@ -1301,7 +1650,7 @@ qeth_dev_rxip_del_store(const char *buf, size_t count, } static ssize_t -qeth_dev_rxip_del4_store(struct device *dev, const char *buf, size_t count) +qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1316,7 +1665,7 @@ static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL, #ifdef CONFIG_QETH_IPV6 static ssize_t -qeth_dev_rxip_add6_show(struct device *dev, char *buf) +qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf) { struct qeth_card *card = dev->driver_data; @@ -1327,7 +1676,7 @@ qeth_dev_rxip_add6_show(struct device *dev, char *buf) } static ssize_t -qeth_dev_rxip_add6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1342,7 +1691,7 @@ static QETH_DEVICE_ATTR(rxip_add6, add6, 0644, qeth_dev_rxip_add6_store); static ssize_t -qeth_dev_rxip_del6_store(struct device *dev, const char *buf, size_t count) +qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev->driver_data; @@ -1375,6 +1724,11 @@ int qeth_create_device_attributes(struct device *dev) { int ret; + struct qeth_card *card = dev->driver_data; + + if (card->info.type == QETH_CARD_TYPE_OSN) + return sysfs_create_group(&dev->kobj, + &qeth_osn_device_attr_group); if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group))) return ret; @@ -1391,18 +1745,32 @@ qeth_create_device_attributes(struct device *dev) sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); + return ret; } - - return ret; + if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){ + sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); + sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); + sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); + sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); + return ret; + } + return 0; } void qeth_remove_device_attributes(struct device *dev) { + struct qeth_card *card = dev->driver_data; + + if (card->info.type == QETH_CARD_TYPE_OSN) + return sysfs_remove_group(&dev->kobj, + &qeth_osn_device_attr_group); + sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); + sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group); } /**********************/ @@ -1439,7 +1807,7 @@ qeth_driver_group_store(struct device_driver *ddrv, const char *buf, } -static DRIVER_ATTR(group, 0200, 0, qeth_driver_group_store); +static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store); static ssize_t qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf, @@ -1467,7 +1835,7 @@ qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf, return count; } -static DRIVER_ATTR(notifier_register, 0200, 0, +static DRIVER_ATTR(notifier_register, 0200, NULL, qeth_driver_notifier_register_store); int