diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/char/raw3270.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth.h | 77 | ||||
-rw-r--r-- | drivers/s390/net/qeth_eddp.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 316 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.h | 15 | ||||
-rw-r--r-- | drivers/s390/net/qeth_proc.c | 250 | ||||
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 10 | ||||
-rw-r--r-- | drivers/s390/net/qeth_tso.h | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 14 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 94 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 110 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 2 |
15 files changed, 463 insertions, 450 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f5b7d360fc1..1026f2bc318 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -1179,12 +1179,12 @@ raw3270_create_attributes(struct raw3270 *rp) //FIXME: check return code sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); rp->clttydev = - class_device_create(class3270, + class_device_create(class3270, NULL, MKDEV(IBM_TTY3270_MAJOR, rp->minor), &rp->cdev->dev, "tty%s", rp->cdev->dev.bus_id); rp->cltubdev = - class_device_create(class3270, + class_device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, rp->minor), &rp->cdev->dev, "tub%s", rp->cdev->dev.bus_id); diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 1c8ad2fcad8..da8c515743e 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -8,7 +8,7 @@ * Author(s): Original Code written by * DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * Rewritten by - * Frank Pavlic (pavlic@de.ibm.com) and + * Frank Pavlic (fpavlic@de.ibm.com) and * Martin Schwidefsky <schwidefsky@de.ibm.com> * * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ @@ -2342,6 +2342,6 @@ __exit lcs_cleanup_module(void) module_init(lcs_init_module); module_exit(lcs_cleanup_module); -MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); +MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 38a2441564d..d238c7ed103 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -8,6 +8,7 @@ #include <linux/trdevice.h> #include <linux/etherdevice.h> #include <linux/if_vlan.h> +#include <linux/ctype.h> #include <net/ipv6.h> #include <linux/in6.h> @@ -24,7 +25,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.142 $" +#define VERSION_QETH_H "$Revision: 1.152 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -718,8 +719,6 @@ struct qeth_reply { atomic_t refcnt; }; -#define QETH_BROADCAST_WITH_ECHO 1 -#define QETH_BROADCAST_WITHOUT_ECHO 2 struct qeth_card_blkt { int time_total; @@ -727,8 +726,10 @@ struct qeth_card_blkt { int inter_packet_jumbo; }; - - +#define QETH_BROADCAST_WITH_ECHO 0x01 +#define QETH_BROADCAST_WITHOUT_ECHO 0x02 +#define QETH_LAYER2_MAC_READ 0x01 +#define QETH_LAYER2_MAC_REGISTERED 0x02 struct qeth_card_info { unsigned short unit_addr2; unsigned short cula; @@ -736,7 +737,7 @@ struct qeth_card_info { __u16 func_level; char mcl_level[QETH_MCL_LENGTH + 1]; int guestlan; - int layer2_mac_registered; + int mac_bits; int portname_required; int portno; char portname[9]; @@ -749,6 +750,7 @@ struct qeth_card_info { int unique_id; struct qeth_card_blkt blkt; __u32 csum_mask; + enum qeth_ipa_promisc_modes promisc_mode; }; struct qeth_card_options { @@ -775,6 +777,7 @@ struct qeth_card_options { enum qeth_threads { QETH_SET_IP_THREAD = 1, QETH_RECOVER_THREAD = 2, + QETH_SET_PROMISC_MODE_THREAD = 4, }; struct qeth_osn_info { @@ -1074,6 +1077,26 @@ qeth_get_qdio_q_format(struct qeth_card *card) } } +static inline int +qeth_isdigit(char * buf) +{ + while (*buf) { + if (!isdigit(*buf++)) + return 0; + } + return 1; +} + +static inline int +qeth_isxdigit(char * buf) +{ + while (*buf) { + if (!isxdigit(*buf++)) + return 0; + } + return 1; +} + static inline void qeth_ipaddr4_to_string(const __u8 *addr, char *buf) { @@ -1090,18 +1113,27 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) int i; start = buf; - for (i = 0; i < 3; i++) { - if (!(end = strchr(start, '.'))) + for (i = 0; i < 4; i++) { + if (i == 3) { + end = strchr(start,0xa); + if (end) + len = end - start; + else + len = strlen(start); + } + else { + end = strchr(start, '.'); + len = end - start; + } + if ((len <= 0) || (len > 3)) return -EINVAL; - len = end - start; memset(abuf, 0, 4); strncpy(abuf, start, len); + if (!qeth_isdigit(abuf)) + return -EINVAL; addr[i] = simple_strtoul(abuf, &tmp, 10); start = end + 1; } - memset(abuf, 0, 4); - strcpy(abuf, start); - addr[3] = simple_strtoul(abuf, &tmp, 10); return 0; } @@ -1128,18 +1160,27 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) tmp_addr = (u16 *)addr; start = buf; - for (i = 0; i < 7; i++) { - if (!(end = strchr(start, ':'))) + for (i = 0; i < 8; i++) { + if (i == 7) { + end = strchr(start,0xa); + if (end) + len = end - start; + else + len = strlen(start); + } + else { + end = strchr(start, ':'); + len = end - start; + } + if ((len <= 0) || (len > 4)) return -EINVAL; - len = end - start; memset(abuf, 0, 5); strncpy(abuf, start, len); + if (!qeth_isxdigit(abuf)) + return -EINVAL; tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); start = end + 1; } - memset(abuf, 0, 5); - strcpy(abuf, start); - tmp_addr[7] = simple_strtoul(abuf, &tmp, 16); return 0; } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 011915d5e24..f94f1f25eec 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -62,7 +62,8 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) for (i = 0; i < ctx->num_pages; ++i) free_page((unsigned long)ctx->pages[i]); kfree(ctx->pages); - kfree(ctx->elements); + if (ctx->elements != NULL) + kfree(ctx->elements); kfree(ctx); } diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 692003c9f89..f8f55cc468b 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -9,10 +9,10 @@ * Author(s): Original Code written by * Utz Bacher (utz.bacher@de.ibm.com) * Rewritten by - * Frank Pavlic (pavlic@de.ibm.com) and + * Frank Pavlic (fpavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.251 $ $Date: 2005/05/04 20:19:18 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -72,7 +72,7 @@ #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.224 $" +#define VERSION_QETH_C "$Revision: 1.251 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -160,6 +160,9 @@ static void qeth_set_multicast_list(struct net_device *); static void +qeth_setadp_promisc_mode(struct qeth_card *); + +static void qeth_notify_processes(void) { /*notify all registered processes */ @@ -515,7 +518,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) QETH_DBF_TEXT(setup, 3, "setoffl"); QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); - + + netif_carrier_off(card->dev); recover_flag = card->state; if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ PRINT_WARN("Stopping card %s interrupted by user!\n", @@ -602,11 +606,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, int found = 0; list_for_each_entry(addr, &card->ip_list, entry) { + if (card->options.layer2) { + if ((addr->type == todo->type) && + (memcmp(&addr->mac, &todo->mac, + OSA_ADDR_LEN) == 0)) { + found = 1; + break; + } + continue; + } if ((addr->proto == QETH_PROT_IPV4) && (todo->proto == QETH_PROT_IPV4) && (addr->type == todo->type) && (addr->u.a4.addr == todo->u.a4.addr) && - (addr->u.a4.mask == todo->u.a4.mask) ){ + (addr->u.a4.mask == todo->u.a4.mask)) { found = 1; break; } @@ -615,12 +628,12 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, (addr->type == todo->type) && (addr->u.a6.pfxlen == todo->u.a6.pfxlen) && (memcmp(&addr->u.a6.addr, &todo->u.a6.addr, - sizeof(struct in6_addr)) == 0)) { + sizeof(struct in6_addr)) == 0)) { found = 1; break; } } - if (found){ + if (found) { addr->users += todo->users; if (addr->users <= 0){ *__addr = addr; @@ -632,7 +645,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, return 0; } } - if (todo->users > 0){ + if (todo->users > 0) { /* for VIPA and RXIP limit refcount to 1 */ if (todo->type != QETH_IP_TYPE_NORMAL) todo->users = 1; @@ -682,12 +695,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) return 0; + if (card->options.layer2) { + if ((tmp->type == addr->type) && + (tmp->is_multicast == addr->is_multicast) && + (memcmp(&tmp->mac, &addr->mac, + OSA_ADDR_LEN) == 0)) { + found = 1; + break; + } + continue; + } if ((tmp->proto == QETH_PROT_IPV4) && (addr->proto == QETH_PROT_IPV4) && (tmp->type == addr->type) && (tmp->is_multicast == addr->is_multicast) && (tmp->u.a4.addr == addr->u.a4.addr) && - (tmp->u.a4.mask == addr->u.a4.mask) ){ + (tmp->u.a4.mask == addr->u.a4.mask)) { found = 1; break; } @@ -697,7 +720,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) (tmp->is_multicast == addr->is_multicast) && (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, - sizeof(struct in6_addr)) == 0) ){ + sizeof(struct in6_addr)) == 0)) { found = 1; break; } @@ -707,7 +730,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) tmp->users += addr->users; else tmp->users += add? 1:-1; - if (tmp->users == 0){ + if (tmp->users == 0) { list_del(&tmp->entry); kfree(tmp); } @@ -738,12 +761,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) unsigned long flags; int rc = 0; - QETH_DBF_TEXT(trace,4,"delip"); - if (addr->proto == QETH_PROT_IPV4) - QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); + QETH_DBF_TEXT(trace, 4, "delip"); + + if (card->options.layer2) + QETH_DBF_HEX(trace, 4, &addr->mac, 6); + else if (addr->proto == QETH_PROT_IPV4) + QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); else { - QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); - QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); + QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); + QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); } spin_lock_irqsave(&card->ip_lock, flags); rc = __qeth_insert_ip_todo(card, addr, 0); @@ -757,12 +783,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) unsigned long flags; int rc = 0; - QETH_DBF_TEXT(trace,4,"addip"); - if (addr->proto == QETH_PROT_IPV4) - QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); + QETH_DBF_TEXT(trace, 4, "addip"); + if (card->options.layer2) + QETH_DBF_HEX(trace, 4, &addr->mac, 6); + else if (addr->proto == QETH_PROT_IPV4) + QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); else { - QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); - QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); + QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); + QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); } spin_lock_irqsave(&card->ip_lock, flags); rc = __qeth_insert_ip_todo(card, addr, 1); @@ -775,7 +803,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) { struct qeth_ipaddr *addr, *tmp; int rc; - +again: list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { if (addr->is_multicast) { spin_unlock_irqrestore(&card->ip_lock, *flags); @@ -784,6 +812,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) if (!rc) { list_del(&addr->entry); kfree(addr); + goto again; } } } @@ -851,6 +880,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) static void qeth_delete_mc_addresses(struct qeth_card *); static void qeth_add_multicast_ipv4(struct qeth_card *); +static void qeth_layer2_add_multicast(struct qeth_card *); #ifdef CONFIG_QETH_IPV6 static void qeth_add_multicast_ipv6(struct qeth_card *); #endif @@ -939,6 +969,24 @@ qeth_register_ip_addresses(void *ptr) return 0; } +/* + * Drive the SET_PROMISC_MODE thread + */ +static int +qeth_set_promisc_mode(void *ptr) +{ + struct qeth_card *card = (struct qeth_card *) ptr; + + daemonize("qeth_setprm"); + QETH_DBF_TEXT(trace,4,"setprm1"); + if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD)) + return 0; + QETH_DBF_TEXT(trace,4,"setprm2"); + qeth_setadp_promisc_mode(card); + qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD); + return 0; +} + static int qeth_recover(void *ptr) { @@ -973,7 +1021,6 @@ void qeth_schedule_recovery(struct qeth_card *card) { QETH_DBF_TEXT(trace,2,"startrec"); - if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) schedule_work(&card->kernel_thread_starter); } @@ -1005,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card) if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); + if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD)) + kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD); if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) kernel_thread(qeth_recover, (void *) card, SIGCHLD); } @@ -1661,7 +1710,6 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) "IP address reset.\n", QETH_CARD_IFNAME(card), card->info.chpid); - netif_carrier_on(card->dev); qeth_schedule_recovery(card); return NULL; case IPA_CMD_MODCCID: @@ -1910,7 +1958,7 @@ qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, { u16 s1, s2; -QETH_DBF_TEXT(trace,4,"osndipa"); + QETH_DBF_TEXT(trace,4,"osndipa"); qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2); s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); @@ -2154,24 +2202,21 @@ qeth_ulp_setup(struct qeth_card *card) } static inline int -qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf, - unsigned int qdio_error, - unsigned int siga_error) +qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, + unsigned int siga_error, const char *dbftext) { - int rc = 0; - if (qdio_error || siga_error) { - QETH_DBF_TEXT(trace, 2, "qdinerr"); - QETH_DBF_TEXT(qerr, 2, "qdinerr"); + QETH_DBF_TEXT(trace, 2, dbftext); + QETH_DBF_TEXT(qerr, 2, dbftext); QETH_DBF_TEXT_(qerr, 2, " F15=%02X", - buf->buffer->element[15].flags & 0xff); + buf->element[15].flags & 0xff); QETH_DBF_TEXT_(qerr, 2, " F14=%02X", - buf->buffer->element[14].flags & 0xff); + buf->element[14].flags & 0xff); QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error); QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error); - rc = 1; + return 1; } - return rc; + return 0; } static inline struct sk_buff * @@ -2720,8 +2765,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, for (i = first_element; i < (first_element + count); ++i) { index = i % QDIO_MAX_BUFFERS_PER_Q; buffer = &card->qdio.in_q->bufs[index]; - if (!((status == QDIO_STATUS_LOOK_FOR_ERROR) && - qeth_check_for_inbound_error(buffer, qdio_err, siga_err))) + if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) && + qeth_check_qdio_errors(buffer->buffer, + qdio_err, siga_err,"qinerr"))) qeth_process_inbound_buffer(card, buffer, index); /* clear buffer and give back to hardware */ qeth_put_buffer_pool_entry(card, buffer->pool_entry); @@ -2736,12 +2782,13 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, static inline int qeth_handle_send_error(struct qeth_card *card, struct qeth_qdio_out_buffer *buffer, - int qdio_err, int siga_err) + unsigned int qdio_err, unsigned int siga_err) { int sbalf15 = buffer->buffer->element[15].flags & 0xff; int cc = siga_err & 3; QETH_DBF_TEXT(trace, 6, "hdsnderr"); + qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr"); switch (cc) { case 0: if (qdio_err){ @@ -2998,7 +3045,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, for(i = first_element; i < (first_element + count); ++i){ buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; /*we only handle the KICK_IT error by doing a recovery */ - if (qeth_handle_send_error(card, buffer, qdio_error, siga_error) + if (qeth_handle_send_error(card, buffer, + qdio_error, siga_error) == QETH_SEND_ERROR_KICK_IT){ netif_stop_queue(card->dev); qeth_schedule_recovery(card); @@ -3240,7 +3288,6 @@ qeth_init_qdio_info(struct qeth_card *card) card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); - /* outbound */ } static int @@ -3682,6 +3729,9 @@ qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card) break; } } + if (rc && !(VLAN_DEV_INFO(dev)->real_dev->priv == (void *)card)) + return 0; + #endif return rc; } @@ -3749,7 +3799,7 @@ qeth_open(struct net_device *dev) if ( (card->info.type != QETH_CARD_TYPE_OSN) && (card->options.layer2) && - (!card->info.layer2_mac_registered)) { + (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) { QETH_DBF_TEXT(trace,4,"nomacadr"); return -EPERM; } @@ -3758,10 +3808,8 @@ qeth_open(struct net_device *dev) card->data.state = CH_STATE_UP; card->state = CARD_STATE_UP; - if (!card->lan_online){ - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - } + if (!card->lan_online && netif_carrier_ok(dev)) + netif_carrier_off(dev); return 0; } @@ -4311,6 +4359,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, out: if (flush_count) qeth_flush_buffers(queue, 0, start_index, flush_count); + else if (!atomic_read(&queue->set_pci_flags_count)) + atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH); /* * queue->state will go from LOCKED -> UNLOCKED or from * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us @@ -4975,6 +5025,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long); static int +qeth_default_setadapterparms_cb(struct qeth_card *card, + struct qeth_reply *reply, + unsigned long data); +static int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16, long, int (*reply_cb) @@ -5301,8 +5355,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) struct qeth_ipaddr *addr; QETH_DBF_TEXT(trace, 4, "frvaddr4"); - if (!card->vlangrp) - return; + rcu_read_lock(); in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); if (!in_dev) @@ -5330,8 +5383,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) struct qeth_ipaddr *addr; QETH_DBF_TEXT(trace, 4, "frvaddr6"); - if (!card->vlangrp) - return; + in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); if (!in6_dev) return; @@ -5351,10 +5403,38 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) } static void +qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid) +{ + if (card->options.layer2 || !card->vlangrp) + return; + qeth_free_vlan_addresses4(card, vid); + qeth_free_vlan_addresses6(card, vid); +} + +static int +qeth_layer2_send_setdelvlan_cb(struct qeth_card *card, + struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(trace, 2, "L2sdvcb"); + cmd = (struct qeth_ipa_cmd *) data; + if (cmd->hdr.return_code) { + PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " + "Continuing\n",cmd->data.setdelvlan.vlan_id, + QETH_CARD_IFNAME(card), cmd->hdr.return_code); + QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command); + QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card)); + QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code); + } + return 0; +} + +static int qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, enum qeth_ipa_cmds ipacmd) { - int rc; struct qeth_ipa_cmd *cmd; struct qeth_cmd_buffer *iob; @@ -5362,15 +5442,8 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd->data.setdelvlan.vlan_id = i; - - rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); - if (rc) { - PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " - "Continuing\n",i, QETH_CARD_IFNAME(card), rc); - QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd); - QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card)); - QETH_DBF_TEXT_(trace, 2, "err%d", rc); - } + return qeth_send_ipa_cmd(card, iob, + qeth_layer2_send_setdelvlan_cb, NULL); } static void @@ -5420,8 +5493,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) qeth_free_vlan_skbs(card, vid); spin_lock_irqsave(&card->vlanlock, flags); /* unregister IP addresses of vlan device */ - qeth_free_vlan_addresses4(card, vid); - qeth_free_vlan_addresses6(card, vid); + qeth_free_vlan_addresses(card, vid); if (card->vlangrp) card->vlangrp->vlan_devices[vid] = NULL; spin_unlock_irqrestore(&card->vlanlock, flags); @@ -5430,6 +5502,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) qeth_set_multicast_list(card->dev); } #endif +/** + * Examine hardware response to SET_PROMISC_MODE + */ +static int +qeth_setadp_promisc_mode_cb(struct qeth_card *card, + struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + struct qeth_ipacmd_setadpparms *setparms; + + QETH_DBF_TEXT(trace,4,"prmadpcb"); + + cmd = (struct qeth_ipa_cmd *) data; + setparms = &(cmd->data.setadapterparms); + + qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd); + if (cmd->hdr.return_code) { + QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code); + setparms->data.mode = SET_PROMISC_MODE_OFF; + } + card->info.promisc_mode = setparms->data.mode; + return 0; +} +/* + * Set promiscuous mode (on or off) (SET_PROMISC_MODE command) + */ +static void +qeth_setadp_promisc_mode(struct qeth_card *card) +{ + enum qeth_ipa_promisc_modes mode; + struct net_device *dev = card->dev; + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(trace, 4, "setprom"); + + if (((dev->flags & IFF_PROMISC) && + (card->info.promisc_mode == SET_PROMISC_MODE_ON)) || + (!(dev->flags & IFF_PROMISC) && + (card->info.promisc_mode == SET_PROMISC_MODE_OFF))) + return; + mode = SET_PROMISC_MODE_OFF; + if (dev->flags & IFF_PROMISC) + mode = SET_PROMISC_MODE_ON; + QETH_DBF_TEXT_(trace, 4, "mode:%x", mode); + + iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE, + sizeof(struct qeth_ipacmd_setadpparms)); + cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); + cmd->data.setadapterparms.data.mode = mode; + qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL); +} /** * set multicast address on card @@ -5444,12 +5569,22 @@ qeth_set_multicast_list(struct net_device *dev) QETH_DBF_TEXT(trace,3,"setmulti"); qeth_delete_mc_addresses(card); + if (card->options.layer2) { + qeth_layer2_add_multicast(card); + goto out; + } qeth_add_multicast_ipv4(card); #ifdef CONFIG_QETH_IPV6 qeth_add_multicast_ipv6(card); #endif +out: if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) schedule_work(&card->kernel_thread_starter); + if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) + return; + if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) + schedule_work(&card->kernel_thread_starter); + } static int @@ -5657,6 +5792,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card) in_dev_put(in4_dev); } +static void +qeth_layer2_add_multicast(struct qeth_card *card) +{ + struct qeth_ipaddr *ipm; + struct dev_mc_list *dm; + + QETH_DBF_TEXT(trace,4,"L2addmc"); + for (dm = card->dev->mc_list; dm; dm = dm->next) { + ipm = qeth_get_addr_buffer(QETH_PROT_IPV4); + if (!ipm) + continue; + memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN); + ipm->is_multicast = 1; + if (!qeth_add_ip(card, ipm)) + kfree(ipm); + } +} + #ifdef CONFIG_QETH_IPV6 static inline void qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) @@ -5716,10 +5869,8 @@ qeth_add_multicast_ipv6(struct qeth_card *card) struct inet6_dev *in6_dev; QETH_DBF_TEXT(trace,4,"chkmcv6"); - if ((card->options.layer2 == 0) && - (!qeth_is_supported(card, IPA_IPV6)) ) + if (!qeth_is_supported(card, IPA_IPV6)) return ; - in6_dev = in6_dev_get(card->dev); if (in6_dev == NULL) return; @@ -5825,10 +5976,10 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card, PRINT_WARN("Error in registering MAC address on " \ "device %s: x%x\n", CARD_BUS_ID(card), cmd->hdr.return_code); - card->info.layer2_mac_registered = 0; + card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; cmd->hdr.return_code = -EIO; } else { - card->info.layer2_mac_registered = 1; + card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac, OSA_ADDR_LEN); PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " @@ -5866,7 +6017,7 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card, cmd->hdr.return_code = -EIO; return 0; } - card->info.layer2_mac_registered = 0; + card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; return 0; } @@ -5874,7 +6025,7 @@ static int qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac) { QETH_DBF_TEXT(trace, 2, "L2Delmac"); - if (!card->info.layer2_mac_registered) + if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) return 0; return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC, qeth_layer2_send_delmac_cb); @@ -5896,7 +6047,7 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) card = (struct qeth_card *) dev->priv; if (!card->options.layer2) { - PRINT_WARN("Setting MAC address on %s is not supported" + PRINT_WARN("Setting MAC address on %s is not supported " "in Layer 3 mode.\n", dev->name); QETH_DBF_TEXT(trace, 3, "setmcLY3"); return -EOPNOTSUPP; @@ -6441,6 +6592,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card, return 0; } + + static int qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) @@ -6481,8 +6634,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, QETH_DBF_TEXT(trace,4,"chgmaccb"); cmd = (struct qeth_ipa_cmd *) data; - memcpy(card->dev->dev_addr, - &cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN); + if (!card->options.layer2 || card->info.guestlan || + !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) { + memcpy(card->dev->dev_addr, + &cmd->data.setadapterparms.data.change_addr.addr, + OSA_ADDR_LEN); + card->info.mac_bits |= QETH_LAYER2_MAC_READ; + } qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); return 0; } @@ -6602,6 +6760,12 @@ qeth_layer2_initialize(struct qeth_card *card) QETH_DBF_TEXT(setup, 2, "doL2init"); QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); + rc = qeth_query_setadapterparms(card); + if (rc) { + PRINT_WARN("could not query adapter parameters on device %s: " + "x%x\n", CARD_BUS_ID(card), rc); + } + rc = qeth_setadpparms_change_macaddr(card); if (rc) { PRINT_WARN("couldn't get MAC address on " @@ -7769,8 +7933,8 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT_(setup, 2, "6err%d", rc); goto out_remove; } -/*maybe it was set offline without ifconfig down - * we can also use this state for recovery purposes*/ + netif_carrier_on(card->dev); + qeth_set_allowed_threads(card, 0xffffffff, 0); if (recover_flag == CARD_STATE_RECOVER) qeth_start_again(card, recovery_mode); @@ -8548,7 +8712,7 @@ EXPORT_SYMBOL(qeth_osn_deregister); EXPORT_SYMBOL(qeth_osn_assist); module_init(qeth_init); module_exit(qeth_exit); -MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); +MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>"); MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \ "Copyright 2000,2003 IBM Corporation\n"); diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c index 30e053d3cac..5f8754addc1 100644 --- a/drivers/s390/net/qeth_mpc.c +++ b/drivers/s390/net/qeth_mpc.c @@ -4,14 +4,14 @@ * Linux on zSeries OSA Express and HiperSockets support * * Copyright 2000,2003 IBM Corporation - * Author(s): Frank Pavlic <pavlic@de.ibm.com> + * Author(s): Frank Pavlic <fpavlic@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com> * */ #include <asm/cio.h> #include "qeth_mpc.h" -const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $"; +const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $"; unsigned char IDX_ACTIVATE_READ[]={ 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 7edc5f1fc0d..864cec5f6c6 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h @@ -6,7 +6,7 @@ * Copyright 2000,2003 IBM Corporation * Author(s): Utz Bacher <utz.bacher@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com> - * Frank Pavlic <pavlic@de.ibm.com> + * Frank Pavlic <fpavlic@de.ibm.com> * */ #ifndef __QETH_MPC_H__ @@ -14,14 +14,14 @@ #include <asm/qeth.h> -#define VERSION_QETH_MPC_H "$Revision: 1.43 $" +#define VERSION_QETH_MPC_H "$Revision: 1.46 $" extern const char *VERSION_QETH_MPC_C; #define IPA_PDU_HEADER_SIZE 0x40 #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) -#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x2a) +#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x29) #define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a) extern unsigned char IPA_PDU_HEADER[]; @@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd { IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, IPA_SETADP_SET_SNMP_CONTROL = 0x0200, IPA_SETADP_READ_SNMP_PARMS = 0x0400, - IPA_SETADP_WRITE_SNMP_PARMS = 0x0800, + IPA_SETADP_SET_PROMISC_MODE = 0x0800, IPA_SETADP_QUERY_CARD_INFO = 0x1000, }; enum qeth_ipa_mac_ops { @@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops { CHANGE_ADDR_ADD_ADDR = 1, CHANGE_ADDR_DEL_ADDR = 2, CHANGE_ADDR_FLUSH_ADDR_TABLE = 4, - - }; +enum qeth_ipa_promisc_modes { + SET_PROMISC_MODE_OFF = 0, + SET_PROMISC_MODE_ON = 1, +}; + /* (SET)DELIP(M) IPA stuff ***************************************************/ struct qeth_ipacmd_setdelip4 { __u8 ip_addr[4]; diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index f2ccfea8fdb..7bf35098831 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.13 $) + * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to procfs. @@ -21,7 +21,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $"; +const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $"; /***** /proc/qeth *****/ #define QETH_PROCFILE_NAME "qeth" @@ -30,30 +30,26 @@ static struct proc_dir_entry *qeth_procfile; static int qeth_procfile_seq_match(struct device *dev, void *data) { - return 1; + return(dev ? 1 : 0); } static void * qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct device *dev; - loff_t nr; - + struct device *dev = NULL; + loff_t nr = 0; + down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - - nr = *offset; - if (nr == 0) + if (*offset == 0) return SEQ_START_TOKEN; - - dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, - NULL, qeth_procfile_seq_match); - - /* get card at pos *offset */ - nr = *offset; - while (nr-- > 1 && dev) + while (1) { dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, NULL, qeth_procfile_seq_match); - return (void *) dev; + if (++nr == *offset) + break; + put_device(dev); + } + return dev; } static void @@ -66,19 +62,14 @@ static void * qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { struct device *prev, *next; - - if (it == SEQ_START_TOKEN) { - next = driver_find_device(&qeth_ccwgroup_driver.driver, - NULL, NULL, qeth_procfile_seq_match); - if (next) - (*offset)++; - return (void *) next; - } - prev = (struct device *) it; + + if (it == SEQ_START_TOKEN) + prev = NULL; + else + prev = (struct device *) it; next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, NULL, qeth_procfile_seq_match); - if (next) - (*offset)++; + (*offset)++; return (void *) next; } @@ -87,7 +78,7 @@ qeth_get_router_str(struct qeth_card *card, int ipv) { int routing_type = 0; - if (ipv == 4){ + if (ipv == 4) { routing_type = card->options.route4.type; } else { #ifdef CONFIG_QETH_IPV6 @@ -154,6 +145,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) card->qdio.in_buf_pool.buf_count); else seq_printf(s, " +++ LAN OFFLINE +++\n"); + put_device(device); } return 0; } @@ -184,51 +176,16 @@ static struct file_operations qeth_procfile_fops = { static struct proc_dir_entry *qeth_perf_procfile; #ifdef CONFIG_QETH_PERF_STATS - -static void * -qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) -{ - struct device *dev = NULL; - int nr; - - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - /* get card at pos *offset */ - dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, - qeth_procfile_seq_match); - - /* get card at pos *offset */ - nr = *offset; - while (nr-- > 1 && dev) - dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, - NULL, qeth_procfile_seq_match); - return (void *) dev; -} - -static void -qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) -{ - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); -} - -static void * -qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) -{ - struct device *prev, *next; - - prev = (struct device *) it; - next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, - NULL, qeth_procfile_seq_match); - if (next) - (*offset)++; - return (void *) next; -} - static int qeth_perf_procfile_seq_show(struct seq_file *s, void *it) { struct device *device; struct qeth_card *card; + + if (it == SEQ_START_TOKEN) + return 0; + device = (struct device *) it; card = device->driver_data; seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", @@ -295,13 +252,14 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) card->perf_stats.outbound_do_qdio_time, card->perf_stats.outbound_do_qdio_cnt ); + put_device(device); return 0; } static struct seq_operations qeth_perf_procfile_seq_ops = { - .start = qeth_perf_procfile_seq_start, - .stop = qeth_perf_procfile_seq_stop, - .next = qeth_perf_procfile_seq_next, + .start = qeth_procfile_seq_start, + .stop = qeth_procfile_seq_stop, + .next = qeth_procfile_seq_next, .show = qeth_perf_procfile_seq_show, }; @@ -324,93 +282,6 @@ static struct file_operations qeth_perf_procfile_fops = { #define qeth_perf_procfile_created 1 #endif /* CONFIG_QETH_PERF_STATS */ -/***** /proc/qeth_ipa_takeover *****/ -#define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover" -static struct proc_dir_entry *qeth_ipato_procfile; - -static void * -qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) -{ - struct device *dev; - loff_t nr; - - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - /* TODO: finish this */ - /* - * maybe SEQ_SATRT_TOKEN can be returned for offset 0 - * output driver settings then; - * else output setting for respective card - */ - - dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, - qeth_procfile_seq_match); - - /* get card at pos *offset */ - nr = *offset; - while (nr-- > 1 && dev) - dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, - NULL, qeth_procfile_seq_match); - return (void *) dev; -} - -static void -qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) -{ - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); -} - -static void * -qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) -{ - struct device *prev, *next; - - prev = (struct device *) it; - next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, - NULL, qeth_procfile_seq_match); - if (next) - (*offset)++; - return (void *) next; -} - -static int -qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) -{ - struct device *device; - struct qeth_card *card; - - /* TODO: finish this */ - /* - * maybe SEQ_SATRT_TOKEN can be returned for offset 0 - * output driver settings then; - * else output setting for respective card - */ - device = (struct device *) it; - card = device->driver_data; - - return 0; -} - -static struct seq_operations qeth_ipato_procfile_seq_ops = { - .start = qeth_ipato_procfile_seq_start, - .stop = qeth_ipato_procfile_seq_stop, - .next = qeth_ipato_procfile_seq_next, - .show = qeth_ipato_procfile_seq_show, -}; - -static int -qeth_ipato_procfile_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &qeth_ipato_procfile_seq_ops); -} - -static struct file_operations qeth_ipato_procfile_fops = { - .owner = THIS_MODULE, - .open = qeth_ipato_procfile_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - int __init qeth_create_procfs_entries(void) { @@ -426,13 +297,7 @@ qeth_create_procfs_entries(void) qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; #endif /* CONFIG_QETH_PERF_STATS */ - qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME, - S_IFREG | 0444, NULL); - if (qeth_ipato_procfile) - qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops; - if (qeth_procfile && - qeth_ipato_procfile && qeth_perf_procfile_created) return 0; else @@ -446,62 +311,5 @@ qeth_remove_procfs_entries(void) remove_proc_entry(QETH_PROCFILE_NAME, NULL); if (qeth_perf_procfile) remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL); - if (qeth_ipato_procfile) - remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL); } - -/* ONLY FOR DEVELOPMENT! -> make it as module */ -/* -static void -qeth_create_sysfs_entries(void) -{ - struct device *dev; - - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - - list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices, - driver_list) - qeth_create_device_attributes(dev); - - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); -} - -static void -qeth_remove_sysfs_entries(void) -{ - struct device *dev; - - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - - list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices, - driver_list) - qeth_remove_device_attributes(dev); - - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); -} - -static int __init -qeth_fs_init(void) -{ - printk(KERN_INFO "qeth_fs_init\n"); - qeth_create_procfs_entries(); - qeth_create_sysfs_entries(); - - return 0; -} - -static void __exit -qeth_fs_exit(void) -{ - printk(KERN_INFO "qeth_fs_exit\n"); - qeth_remove_procfs_entries(); - qeth_remove_sysfs_entries(); -} - - -module_init(qeth_fs_init); -module_exit(qeth_fs_exit); - -MODULE_LICENSE("GPL"); -*/ diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index f91a02db574..0ea185f70f7 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.55 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.60 $) * * 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 <tspat@de.ibm.com> - * Frank Pavlic <pavlic@de.ibm.com> + * Frank Pavlic <fpavlic@de.ibm.com> * */ #include <linux/list.h> @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $"; /*****************************************************************************/ /* */ @@ -160,7 +160,7 @@ qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const 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); @@ -1117,7 +1117,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, start = buf; /* get address string */ end = strchr(start, '/'); - if (!end){ + if (!end || (end-start >= 49)){ PRINT_WARN("Invalid format for ipato_addx/delx. " "Use <ip addr>/<mask bits>\n"); return -EINVAL; diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index ad33e6f466f..3c50b6f24f5 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -1,13 +1,13 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $) + * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $) * * Header file for qeth TCP Segmentation Offload support. * * Copyright 2004 IBM Corporation * - * Author(s): Frank Pavlic <pavlic@de.ibm.com> + * Author(s): Frank Pavlic <fpavlic@de.ibm.com> * - * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.8 $ $Date: 2005/05/04 20:19:18 $ * */ #ifndef __QETH_TSO_H__ diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index c218b5c944a..5e84c5aa777 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -996,6 +996,20 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) spin_lock_init(&adapter->fsf_req_list_lock); INIT_LIST_HEAD(&adapter->fsf_req_list_head); + /* initialize debug locks */ + + spin_lock_init(&adapter->erp_dbf_lock); + spin_lock_init(&adapter->hba_dbf_lock); + spin_lock_init(&adapter->san_dbf_lock); + spin_lock_init(&adapter->scsi_dbf_lock); + + /* initialize error recovery stuff */ + + rwlock_init(&adapter->erp_lock); + sema_init(&adapter->erp_ready_sem, 0); + INIT_LIST_HEAD(&adapter->erp_ready_head); + INIT_LIST_HEAD(&adapter->erp_running_head); + /* initialize abort lock */ rwlock_init(&adapter->abort_lock); diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 826fb3b0060..95599719f8a 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -926,7 +926,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) char dbf_name[DEBUG_MAX_NAME_LEN]; /* debug feature area which records recovery activity */ - spin_lock_init(&adapter->erp_dbf_lock); sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, sizeof(struct zfcp_erp_dbf_record)); @@ -936,7 +935,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) debug_set_level(adapter->erp_dbf, 3); /* debug feature area which records HBA (FSF and QDIO) conditions */ - spin_lock_init(&adapter->hba_dbf_lock); sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_hba_dbf_record)); @@ -947,7 +945,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) debug_set_level(adapter->hba_dbf, 3); /* debug feature area which records SAN command failures and recovery */ - spin_lock_init(&adapter->san_dbf_lock); sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_san_dbf_record)); @@ -958,7 +955,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) debug_set_level(adapter->san_dbf, 6); /* debug feature area which records SCSI command failures and recovery */ - spin_lock_init(&adapter->scsi_dbf_lock); sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_scsi_dbf_record)); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 023f4e558ae..ee7314d8c2d 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1071,11 +1071,6 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter) atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); - rwlock_init(&adapter->erp_lock); - INIT_LIST_HEAD(&adapter->erp_ready_head); - INIT_LIST_HEAD(&adapter->erp_running_head); - sema_init(&adapter->erp_ready_sem, 0); - retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); if (retval < 0) { ZFCP_LOG_NORMAL("error: creation of erp thread failed for " @@ -2248,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: zfcp_fsf_init - * - * purpose: initializes FSF operation for the specified adapter - * - * returns: 0 - succesful initialization of FSF operation - * !0 - failed to initialize FSF operation - */ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) { - int xconfig, xport; + int retval; - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &erp_action->adapter->status)) { + if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &erp_action->adapter->status)) && + (erp_action->adapter->adapter_features & + FSF_FEATURE_HBAAPI_MANAGEMENT)) { zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); atomic_set(&erp_action->adapter->erp_counter, 0); return ZFCP_ERP_FAILED; } - xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); - xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); - if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) + retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); + if (retval == ZFCP_ERP_FAILED) + return ZFCP_ERP_FAILED; + + retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); + if (retval == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); @@ -2359,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) { - int retval = ZFCP_ERP_SUCCEEDED; + int ret; int retries; int sleep; struct zfcp_adapter *adapter = erp_action->adapter; atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - for (retries = 0; ; retries++) { - ZFCP_LOG_DEBUG("Doing exchange port data\n"); + retries = 0; + do { + write_lock(&adapter->erp_lock); zfcp_erp_action_to_running(erp_action); + write_unlock(&adapter->erp_lock); zfcp_erp_timeout_init(erp_action); - if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { - retval = ZFCP_ERP_FAILED; - debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); - ZFCP_LOG_INFO("error: initiation of exchange of " - "port data failed for adapter %s\n", - zfcp_get_busid_by_adapter(adapter)); - break; + ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); + if (ret == -EOPNOTSUPP) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); + return ZFCP_ERP_SUCCEEDED; + } else if (ret) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); + return ZFCP_ERP_FAILED; } - debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); - ZFCP_LOG_DEBUG("Xchange underway\n"); + debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); - /* - * Why this works: - * Both the normal completion handler as well as the timeout - * handler will do an 'up' when the 'exchange port data' - * request completes or times out. Thus, the signal to go on - * won't be lost utilizing this semaphore. - * Furthermore, this 'adapter_reopen' action is - * guaranteed to be the only action being there (highest action - * which prevents other actions from being created). - * Resulting from that, the wake signal recognized here - * _must_ be the one belonging to the 'exchange port - * data' request. - */ down(&adapter->erp_ready_sem); if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_INFO("error: exchange of port data " @@ -2401,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) zfcp_get_busid_by_adapter(adapter)); break; } - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status)) break; - ZFCP_LOG_DEBUG("host connection still initialising... " - "waiting and retrying...\n"); - /* sleep a little bit before retry */ - sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? - ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : - ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; - msleep(jiffies_to_msecs(sleep)); - } - - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status)) { - ZFCP_LOG_INFO("error: exchange of port data for " - "adapter %s failed\n", - zfcp_get_busid_by_adapter(adapter)); - retval = ZFCP_ERP_FAILED; - } + if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { + sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; + retries++; + } else + sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; + schedule_timeout(sleep); + } while (1); - return retval; + return ZFCP_ERP_SUCCEEDED; } /* diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 3b0fc1163f5..59587951c84 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -554,6 +554,17 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, struct fsf_link_down_info *link_down) { + if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status)) + return; + + atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); + + if (link_down == NULL) { + zfcp_erp_adapter_reopen(adapter, 0); + return; + } + switch (link_down->error_code) { case FSF_PSQ_LINK_NO_LIGHT: ZFCP_LOG_NORMAL("The local link to adapter %s is down " @@ -634,20 +645,15 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, link_down->explanation_code, link_down->vendor_specific_code); - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status)) { - atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status); - switch (link_down->error_code) { - case FSF_PSQ_LINK_NO_LIGHT: - case FSF_PSQ_LINK_WRAP_PLUG: - case FSF_PSQ_LINK_NO_FCP: - case FSF_PSQ_LINK_FIRMWARE_UPDATE: - zfcp_erp_adapter_reopen(adapter, 0); - break; - default: - zfcp_erp_adapter_failed(adapter); - } + switch (link_down->error_code) { + case FSF_PSQ_LINK_NO_LIGHT: + case FSF_PSQ_LINK_WRAP_PLUG: + case FSF_PSQ_LINK_NO_FCP: + case FSF_PSQ_LINK_FIRMWARE_UPDATE: + zfcp_erp_adapter_reopen(adapter, 0); + break; + default: + zfcp_erp_adapter_failed(adapter); } } @@ -919,30 +925,36 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: ZFCP_LOG_INFO("Physical link to adapter %s is down\n", zfcp_get_busid_by_adapter(adapter)); + zfcp_fsf_link_down_info_eval(adapter, + (struct fsf_link_down_info *) + &status_buffer->payload); break; case FSF_STATUS_READ_SUB_FDISC_FAILED: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to failed FDISC login\n", - zfcp_get_busid_by_adapter(adapter)); + zfcp_get_busid_by_adapter(adapter)); + zfcp_fsf_link_down_info_eval(adapter, + (struct fsf_link_down_info *) + &status_buffer->payload); break; case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to firmware update on adapter\n", zfcp_get_busid_by_adapter(adapter)); + zfcp_fsf_link_down_info_eval(adapter, NULL); break; default: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to unknown reason\n", zfcp_get_busid_by_adapter(adapter)); + zfcp_fsf_link_down_info_eval(adapter, NULL); }; - zfcp_fsf_link_down_info_eval(adapter, - (struct fsf_link_down_info *) &status_buffer->payload); break; case FSF_STATUS_READ_LINK_UP: ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " - "Restarting operations on this adapter\n", - zfcp_get_busid_by_adapter(adapter)); + "Restarting operations on this adapter\n", + zfcp_get_busid_by_adapter(adapter)); /* All ports should be marked as ready to run again */ zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, @@ -2191,13 +2203,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, return -EOPNOTSUPP; } - timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); - if (!timer) - return -ENOMEM; - /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, - 0, 0, &lock_flags, &fsf_req); + erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, + 0, &lock_flags, &fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "exchange port data request for" @@ -2205,25 +2214,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, zfcp_get_busid_by_adapter(adapter)); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - goto out; - } - - if (erp_action) { - erp_action->fsf_req = fsf_req; - fsf_req->erp_action = erp_action; + return retval; } if (data) - fsf_req->data = (unsigned long) data; + fsf_req->data = (unsigned long) data; sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; - init_timer(timer); - timer->function = zfcp_fsf_request_timeout_handler; - timer->data = (unsigned long) adapter; - timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; + if (erp_action) { + erp_action->fsf_req = fsf_req; + fsf_req->erp_action = erp_action; + timer = &erp_action->timer; + } else { + timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC); + if (!timer) { + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + zfcp_fsf_req_free(fsf_req); + return -ENOMEM; + } + init_timer(timer); + timer->function = zfcp_fsf_request_timeout_handler; + timer->data = (unsigned long) adapter; + timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; + } retval = zfcp_fsf_req_send(fsf_req, timer); if (retval) { @@ -2233,23 +2250,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, zfcp_fsf_req_free(fsf_req); if (erp_action) erp_action->fsf_req = NULL; + else + kfree(timer); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - goto out; + return retval; } - ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", - zfcp_get_busid_by_adapter(adapter)); - - write_unlock_irqrestore(&adapter->request_queue.queue_lock, - lock_flags); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - wait_event(fsf_req->completion_wq, - fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - del_timer_sync(timer); - zfcp_fsf_req_free(fsf_req); - out: - kfree(timer); + if (!erp_action) { + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + del_timer_sync(timer); + zfcp_fsf_req_free(fsf_req); + kfree(timer); + } return retval; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3dcd1bfba3b..66608d13a63 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -179,7 +179,7 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) struct zfcp_adapter *adapter; struct zfcp_unit *unit; unsigned long flags; - int retval = -ENODEV; + int retval = -ENXIO; adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; if (!adapter) |