From a144b646fd1a9719151d36d08a962a9d2523b2c9 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 11 Aug 2003 00:02:04 -0700 Subject: [SCTP] Fix bugs in sysctl set/get of sctp rto parameters. --- net/sctp/sysctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index cdcf6d09d24f..edffe9cc8f21 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -214,7 +214,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (olen != sizeof (int)) return -EINVAL; } - if (put_user((*(int *)(table->data) / HZ) * 1000, + if (put_user((*(int *)(table->data) * 1000) / HZ, (int *)oldval) || (oldlenp && put_user(sizeof (int), oldlenp))) return -EFAULT; @@ -228,7 +228,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (get_user(new, (int *)newval)) return -EFAULT; - *(int *)(table->data) = (new * HZ) * 1000; + *(int *)(table->data) = (new * HZ) / 1000; } return 1; } -- cgit v1.2.3 From 5c70f0a4734dc1424dbf9eb5215f9591afd750ba Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Sun, 24 Aug 2003 22:17:26 -0700 Subject: [SCTP] draft07 API changes: sctp_getpaddrs(), sctp_getladdrs() now return a packed array of sockaddr_in/sockaddr_in6 structures instead of an array of sockaddr_storage structures. --- include/net/sctp/user.h | 8 +++++--- net/sctp/socket.c | 33 +++++++++++++++++---------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index da96859dba92..45f96479510f 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -551,13 +551,15 @@ struct sctp_status { }; /* - * 8.3, 8.5 get all peer/local addresses on a socket - * This parameter struct is for getsockopt + * 8.3, 8.5 get all peer/local addresses in an association. + * This parameter struct is used by SCTP_GET_PEER_ADDRS and + * SCTP_GET_LOCAL_ADDRS socket options used internally to implement + * sctp_getpaddrs() and sctp_getladdrs() API. */ struct sctp_getaddrs { sctp_assoc_t assoc_id; int addr_num; - struct sockaddr_storage *addrs; + struct sockaddr *addrs; }; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 99c4a4914d08..0fb64f708c5a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2552,7 +2552,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int * } static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -2565,9 +2565,7 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - /* - * For UDP-style sockets, id specifies the association to query. - */ + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, id); if (!asoc) return -EINVAL; @@ -2582,16 +2580,17 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, } static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_transport *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2600,21 +2599,21 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; - /* - * For UDP-style sockets, id specifies the association to query. - */ + + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, getaddrs.assoc_id); if (!asoc) return -EINVAL; - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen ; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2673,9 +2672,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_sockaddr_entry *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2699,16 +2699,17 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, bp = &asoc->base.bind_addr; } - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &bp->address_list) { from = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &from->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; } -- cgit v1.2.3 From b5c67280c349e9341bfaa9d0e6bbfa176344bb2e Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Wed, 27 Aug 2003 01:02:04 -0700 Subject: [SCTP] SCTP_SET_PEER_PRIMARY socket option support. (Kevin Gao) --- include/linux/sctp.h | 9 ++++++- include/net/sctp/sctp.h | 4 ++- include/net/sctp/sm.h | 6 ++++- include/net/sctp/structs.h | 5 +++- net/sctp/associola.c | 23 +++++++++++++++- net/sctp/primitive.c | 14 ++++++++++ net/sctp/sm_make_chunk.c | 48 +++++++++++++++++++++++++++++++-- net/sctp/socket.c | 67 +++++++++++++++++++++++++++++++++++++++++++--- 8 files changed, 166 insertions(+), 10 deletions(-) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index 6ebaff34570c..6131e3c9aa45 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -42,6 +42,8 @@ * randall@sctp.chicago.il.us * kmorneau@cisco.com * qxie1@email.mot.com + * Sridhar Samudrala + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -507,6 +509,11 @@ typedef struct sctp_cwr_chunk { * The ASCONF Parameter Response is used in the ASCONF-ACK to * report status of ASCONF processing. */ +typedef struct sctp_addip_param { + sctp_paramhdr_t param_hdr; + __u32 crr_id; +}sctp_addip_param_t __attribute__((packed)); + typedef struct sctp_addiphdr { __u32 serial; __u8 params[0]; diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 506fd2cb1305..4d9d69a3d145 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * * This file is part of the SCTP kernel reference Implementation @@ -40,6 +40,7 @@ * Sridhar Samudrala * Ardelle Fan * Ryan Layer + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -145,6 +146,7 @@ int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); int sctp_primitive_ABORT(struct sctp_association *, void *arg); int sctp_primitive_SEND(struct sctp_association *, void *arg); int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); +int sctp_primitive_ASCONF(struct sctp_association *, void *arg); /* * sctp/crc32c.c diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 28d4c6409247..40cb876aaf96 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -41,6 +41,7 @@ * Sridhar Samudrala * Daisy Chang * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -268,6 +269,9 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, struct sctp_chunk *asconf, int vparam_len); +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); + void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f77373f18e7e..d6199d3a2081 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2003 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -45,6 +45,7 @@ * Ardelle Fan * Ryan Layer * Anup Pemmaiah + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1688,6 +1689,8 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport( void sctp_assoc_update_retran_path(struct sctp_association *); struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, const union sctp_addr *); +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr); struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, const union sctp_addr *address, const int gfp); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 849b7a589ac0..c1323ddd5576 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll * @@ -42,6 +42,7 @@ * Sridhar Samudrala * Daisy Chang * Ryan Layer + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1155,3 +1156,23 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc, return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3, asoc->ep->base.bind_addr.port, gfp); } + +/* Lookup laddr in the bind address list of an association. */ +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr) +{ + int found; + + sctp_read_lock(&asoc->base.addr_lock); + if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && + sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_sk(asoc->base.sk))) { + found = 1; + goto out; + } + + found = 0; +out: + sctp_read_unlock(&asoc->base.addr_lock); + return found; +} diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 243b1d5a8657..3a7ebfcc1fdb 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -39,6 +39,7 @@ * Narasimha Budihal * Karl Knutson * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND); */ DECLARE_PRIMITIVE(REQUESTHEARTBEAT); + +/* ADDIP +* 3.1.1 Address Configuration Change Chunk (ASCONF) +* +* This chunk is used to communicate to the remote endpoint one of the +* configuration change requests that MUST be acknowledged. The +* information carried in the ASCONF Chunk uses the form of a +* Type-Length-Value (TLV), as described in "3.2.1 Optional/ +* Variable-length Parameter Format" in RFC2960 [5], forall variable +* parameters. +*/ + +DECLARE_PRIMITIVE(ASCONF); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index bf3f373d9feb..9f32aa219158 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * Copyright (C) IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -48,6 +48,7 @@ * Sridhar Samudrala * Daisy Chang * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -2135,7 +2136,50 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, retval->subh.addip_hdr = sctp_addto_chunk(retval, sizeof(asconf), &asconf); retval->param_hdr.v = - sctp_addto_chunk(retval, addrlen, &addr); + sctp_addto_chunk(retval, addrlen, &addrparam); + + return retval; +} + +/* ADDIP + * 3.2.4 Set Primary IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type =0xC004 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Create an ASCONF chunk with Set Primary IP address parameter. + */ +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr) +{ + sctp_addip_param_t param; + struct sctp_chunk *retval; + int len = sizeof(param); + union sctp_params addrparam; + int addrlen; + + addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); + if (!addrlen) + return NULL; + len += addrlen; + + /* Create the chunk and make asconf header. */ + retval = sctp_make_asconf(asoc, addr, len); + if (!retval) + return NULL; + + param.param_hdr.type = SCTP_PARAM_SET_PRIMARY; + param.param_hdr.length = htons(len); + param.crr_id = 0; + + sctp_addto_chunk(retval, sizeof(param), ¶m); + sctp_addto_chunk(retval, addrlen, &addrparam); return retval; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0fb64f708c5a..9a99fe3bd558 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1,6 +1,7 @@ -/* Copyright (c) 1999-2000 Cisco, Inc. +/* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 + * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -50,6 +51,7 @@ * Ardelle Fan * Ryan Layer * Anup Pemmaiah + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1522,7 +1524,7 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, return 0; } -/* 7.1.10 Set Peer Primary Address (SCTP_PRIMARY_ADDR) +/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the @@ -1727,6 +1729,62 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen) return 0; } + +/* + * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) + * + * Requests that the peer mark the enclosed address as the association + * primary. The enclosed address must be one of the association's + * locally bound addresses. The following structure is used to make a + * set primary request: + */ +static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval, + int optlen) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc = NULL; + struct sctp_setpeerprim prim; + struct sctp_chunk *chunk; + int err; + + sp = sctp_sk(sk); + ep = sp->ep; + + if (optlen != sizeof(struct sctp_setpeerprim)) + return -EINVAL; + + if (copy_from_user(&prim, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); + if (!asoc) + return -EINVAL; + + if (!sctp_state(asoc, ESTABLISHED)) + return -ENOTCONN; + + if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) + return -EADDRNOTAVAIL; + + /* Create an ASCONF chunk with SET_PRIMARY parameter */ + chunk = sctp_make_asconf_set_prim(asoc, + (union sctp_addr *)&prim.sspp_addr); + if (!chunk) + return -ENOMEM; + + err = sctp_primitive_ASCONF(asoc, chunk); + if (err) { + sctp_chunk_free(chunk); + return err; + } + + SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); + + return 0; +} + + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -1809,6 +1867,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_PRIMARY_ADDR: retval = sctp_setsockopt_primary_addr(sk, optval, optlen); break; + case SCTP_SET_PEER_PRIMARY_ADDR: + retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen); + break; case SCTP_NODELAY: retval = sctp_setsockopt_nodelay(sk, optval, optlen); break; -- cgit v1.2.3 From f1079649f0689a786015a67559f12f13bbcef2b4 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Fri, 29 Aug 2003 02:24:15 -0700 Subject: [SCTP] draft07 API changes: sctp_bindx() now takes a packed array of sockaddr_in/sockaddr_in6 structures instead of an array of sockaddr_storage structures. --- include/net/sctp/sctp.h | 6 + net/sctp/socket.c | 339 +++++++++++++++++++++--------------------------- 2 files changed, 153 insertions(+), 192 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 4d9d69a3d145..a456d5a99d37 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -406,6 +406,12 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list) return result; } +/* Tests if the list has one and only one entry. */ +static inline int sctp_list_single_entry(struct list_head *head) +{ + return ((head->next != head) && (head->next == head->prev)); +} + /* Calculate the size (in bytes) occupied by the data of an iovec. */ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9a99fe3bd558..a071384084eb 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -95,8 +95,8 @@ static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); static void sctp_wait_for_close(struct sock *sk, long timeo); static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int); -static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int); -static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); +static int sctp_bindx_add(struct sock *, struct sockaddr *, int); +static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_autobind(struct sock *sk); static void sctp_sock_migrate(struct sock *, struct sock *, @@ -172,10 +172,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk, * sd - the socket descriptor returned by socket(). * addr - the address structure (struct sockaddr_in or struct * sockaddr_in6 [RFC 2553]), - * addrlen - the size of the address structure. - * - * The caller should use struct sockaddr_storage described in RFC 2553 - * to represent addr for portability reason. + * addr_len - the size of the address structure. */ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { @@ -300,112 +297,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) return ret; } -/* API 8.1 sctp_bindx() - * - * The syntax of sctp_bindx() is, - * - * ret = sctp_bindx(int sd, - * struct sockaddr_storage *addrs, - * int addrcnt, - * int flags); - * - * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. - * If the sd is an IPv6 socket, the addresses passed can either be IPv4 - * or IPv6 addresses. - * - * A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see - * section 3.1.2 for this usage. - * - * addrs is a pointer to an array of one or more socket addresses. Each - * address is contained in a struct sockaddr_storage, so each address is - * fixed length. The caller specifies the number of addresses in the - * array with addrcnt. - * - * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1, - * and sets errno to the appropriate error code. [ Editor's note: need - * to fill in all error code? ] - * - * For SCTP, the port given in each socket address must be the same, or - * sctp_bindx() will fail, setting errno to EINVAL . - * - * The flags parameter is formed from the bitwise OR of zero or - * more of the following currently defined flags: - * - * SCTP_BINDX_ADD_ADDR - * SCTP_BINDX_REM_ADDR - * - * SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the - * association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given - * addresses from the association. The two flags are mutually exclusive; - * if both are given, sctp_bindx() will fail with EINVAL. A caller may not - * remove all addresses from an association; sctp_bindx() will reject such - * an attempt with EINVAL. - * - * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate - * additional addresses with an endpoint after calling bind(). Or use - * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening - * socket is associated with so that no new association accepted will be - * associated with those addresses. - * - * SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default - * behavior for sctp_bindx() when no flags are given. - * - * Adding and removing addresses from a connected association is optional - * functionality. Implementations that do not support this functionality - * should return EOPNOTSUPP. - * - * NOTE: This could be integrated into sctp_setsockopt_bindx(), - * but keeping it this way makes it easier if sometime sys_bindx is - * added. - */ - -/* Unprotected by locks. Call only with socket lock sk->sk_lock held! See - * sctp_bindx() for a lock-protected call. - */ - -static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, - int addrcnt, int flags) -{ - int retval = 0; - - SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, " - "flags: %s)\n", sk, addrs, addrcnt, - (SCTP_BINDX_ADD_ADDR == flags) ? "ADD" : - ((SCTP_BINDX_REM_ADDR == flags) ? "REM" : "BOGUS")); - - switch (flags) { - case SCTP_BINDX_ADD_ADDR: - retval = sctp_bindx_add(sk, addrs, addrcnt); - break; - - case SCTP_BINDX_REM_ADDR: - retval = sctp_bindx_rem(sk, addrs, addrcnt); - break; - - default: - retval = -EINVAL; - break; - }; - - return retval; -} - -/* BINDX with locks. - * - * NOTE: Currently unused at all ... - */ -int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, - int flags) -{ - int retval; - - sctp_lock_sock(sk); - retval = __sctp_bindx(sk, addrs, addrcnt, flags); - sctp_release_sock(sk); - - return retval; -} - /* Add a list of addresses as bind addresses to local endpoint or * association. * @@ -416,41 +307,39 @@ int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, * If any of them fails, then the operation will be reversed and the * ones that were added will be removed. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; - int addr_len; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { /* The list may contain either IPv4 or IPv6 address; * determine the address length for walking thru the list. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - addr_len = sizeof(struct sockaddr_in); - break; - - case AF_INET6: - addr_len = sizeof(struct sockaddr_in6); - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_add; - }; + } - retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt], - addr_len); + retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, + af->sockaddr_len); + + addr_buf += af->sockaddr_len; err_bindx_add: if (retval < 0) { - /* Failed. Cleanup the ones that has been added */ + /* Failed. Cleanup the ones that have been added */ if (cnt > 0) sctp_bindx_rem(sk, addrs, cnt); return retval; @@ -473,9 +362,9 @@ err_bindx_add: * At least one address has to be left; if only one address is * available, the operation will return -EBUSY. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -483,50 +372,41 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) struct sctp_bind_addr *bp = &ep->base.bind_addr; int retval = 0; union sctp_addr saveaddr; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { - /* If there is only one bind address, there is nothing more - * to be removed (we need at least one address here). + /* If the bind address list is empty or if there is only one + * bind address, there is nothing more to be removed (we need + * at least one address here). */ - if (list_empty(&bp->address_list)) { + if (list_empty(&bp->address_list) || + (sctp_list_single_entry(&bp->address_list))) { retval = -EBUSY; goto err_bindx_rem; } /* The list may contain either IPv4 or IPv6 address; - * determine the address length for walking thru the list. + * determine the address length to copy the address to + * saveaddr. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); - /* Verify the port. */ - if (saveaddr.v4.sin_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - case AF_INET6: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v6.sin6_port = - ntohs(saveaddr.v6.sin6_port); - /* verify the port */ - if (saveaddr.v6.sin6_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_rem; - }; + } + memcpy(&saveaddr, sa_addr, af->sockaddr_len); + saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); + if (saveaddr.v4.sin_port != bp->port) { + retval = -EINVAL; + goto err_bindx_rem; + } /* FIXME - There is probably a need to check if sk->sk_saddr and * sk->sk_rcv_addr are currently set to one of the addresses to @@ -543,6 +423,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); + addr_buf += af->sockaddr_len; err_bindx_rem: if (retval < 0) { /* Failed. Add the ones that has been removed back */ @@ -555,18 +436,62 @@ err_bindx_rem: return retval; } -/* Helper for tunneling sys_bindx() requests through sctp_setsockopt() +/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() + * + * API 8.1 + * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, + * int flags); + * + * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. + * If the sd is an IPv6 socket, the addresses passed can either be IPv4 + * or IPv6 addresses. + * + * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see + * Section 3.1.2 for this usage. + * + * addrs is a pointer to an array of one or more socket addresses. Each + * address is contained in its appropriate structure (i.e. struct + * sockaddr_in or struct sockaddr_in6) the family of the address type + * must be used to distengish the address length (note that this + * representation is termed a "packed array" of addresses). The caller + * specifies the number of addresses in the array with addrcnt. + * + * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns + * -1, and sets errno to the appropriate error code. + * + * For SCTP, the port given in each socket address must be the same, or + * sctp_bindx() will fail, setting errno to EINVAL. + * + * The flags parameter is formed from the bitwise OR of zero or more of + * the following currently defined flags: + * + * SCTP_BINDX_ADD_ADDR + * + * SCTP_BINDX_REM_ADDR + * + * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the + * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given + * addresses from the association. The two flags are mutually exclusive; + * if both are given, sctp_bindx() will fail with EINVAL. A caller may + * not remove all addresses from an association; sctp_bindx() will + * reject such an attempt with EINVAL. + * + * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate + * additional addresses with an endpoint after calling bind(). Or use + * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening + * socket is associated with so that no new association accepted will be + * associated with those addresses. If the endpoint supports dynamic + * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a + * endpoint to send the appropriate message to the peer to change the + * peers address lists. + * + * Adding and removing addresses from a connected association is + * optional functionality. Implementations that do not support this + * functionality should return EOPNOTSUPP. * * Basically do nothing but copying the addresses from user to kernel - * land and invoking sctp_bindx on the sk. This is used for tunneling - * the sctp_bindx() [sys_bindx()] request through sctp_setsockopt() - * from userspace. - * - * Note I don't use move_addr_to_kernel(): the reason is we would be - * iterating over an array of struct sockaddr_storage passing always - * what we know is a good size (sizeof (struct sock...)), so it is - * pointless. Instead check the whole area for read access and copy - * it. + * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. + * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. * * We don't use copy_from_user() for optimization: we first do the * sanity checks (buffer size -fast- and access check-healthy @@ -586,38 +511,70 @@ err_bindx_rem: * * Returns 0 if ok, <0 errno code on error. */ -SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, - struct sockaddr_storage *addrs, - int addrssize, int op) +SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs, + int addrs_size, int op) { - struct sockaddr_storage *kaddrs; + struct sockaddr *kaddrs; int err; - size_t addrcnt; + int addrcnt = 0; + int walk_size = 0; + struct sockaddr *sa_addr; + void *addr_buf; + struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p" - " addrssize %d opt %d\n", sk, addrs, addrssize, op); + SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" + " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); - /* Do we have an integer number of structs sockaddr_storage? */ - if (unlikely(addrssize <= 0 || - addrssize % sizeof(struct sockaddr_storage) != 0)) + if (unlikely(addrs_size <= 0)) return -EINVAL; /* Check the user passed a healthy pointer. */ - if (unlikely(!access_ok(VERIFY_READ, addrs, addrssize))) + if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) return -EFAULT; /* Alloc space for the address array in kernel memory. */ - kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL); + kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); if (unlikely(!kaddrs)) return -ENOMEM; - if (copy_from_user(kaddrs, addrs, addrssize)) { + if (__copy_from_user(kaddrs, addrs, addrs_size)) { kfree(kaddrs); return -EFAULT; } - addrcnt = addrssize / sizeof(struct sockaddr_storage); - err = __sctp_bindx(sk, kaddrs, addrcnt, op); /* Do the work. */ + /* Walk through the addrs buffer and count the number of addresses. */ + addr_buf = kaddrs; + while (walk_size < addrs_size) { + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + + /* If the address family is not supported or if this address + * causes the address buffer to overflow return EINVAL. + */ + if (!af || (walk_size + af->sockaddr_len) > addrs_size) { + kfree(kaddrs); + return -EINVAL; + } + addrcnt++; + addr_buf += af->sockaddr_len; + walk_size += af->sockaddr_len; + } + + /* Do the work. */ + switch (op) { + case SCTP_BINDX_ADD_ADDR: + err = sctp_bindx_add(sk, kaddrs, addrcnt); + break; + + case SCTP_BINDX_REM_ADDR: + err = sctp_bindx_rem(sk, kaddrs, addrcnt); + break; + + default: + err = -EINVAL; + break; + }; + kfree(kaddrs); return err; @@ -1829,16 +1786,14 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case SCTP_SOCKOPT_BINDX_ADD: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_ADD_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_ADD_ADDR); break; case SCTP_SOCKOPT_BINDX_REM: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_REM_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_REM_ADDR); break; case SCTP_DISABLE_FRAGMENTS: -- cgit v1.2.3 From f04759b8c1c2dc830236806cc809e28d8db4e292 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 1 Sep 2003 01:45:18 +0100 Subject: [AGPGART] Various renames for AMD64 GART driver. - Remove references to 8151, as its not specific to this driver - K8 & x86-64 is deprecated in favour of amd64 --- arch/i386/defconfig | 2 +- arch/x86_64/defconfig | 2 +- arch/x86_64/kernel/pci-gart.c | 4 +- drivers/char/agp/Kconfig | 3 +- drivers/char/agp/Makefile | 2 +- drivers/char/agp/amd-k8-agp.c | 544 ------------------------------------------ drivers/char/agp/amd64-agp.c | 544 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 550 insertions(+), 551 deletions(-) delete mode 100644 drivers/char/agp/amd-k8-agp.c create mode 100644 drivers/char/agp/amd64-agp.c diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 150ff18161a8..c51259a5dbf4 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -718,7 +718,7 @@ CONFIG_AGP=y # CONFIG_AGP_ALI is not set # CONFIG_AGP_ATI is not set # CONFIG_AGP_AMD is not set -# CONFIG_AGP_AMD_8151 is not set +# CONFIG_AGP_AMD64 is not set CONFIG_AGP_INTEL=y # CONFIG_AGP_NVIDIA is not set # CONFIG_AGP_SIS is not set diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 3018aafd56fd..c5f5dc2c3be9 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -558,7 +558,7 @@ CONFIG_RTC=y # # CONFIG_FTAPE is not set CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y +CONFIG_AGP_AMD64=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 6842d5823465..3510604677d8 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -675,7 +675,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) return -1; } -extern int agp_amdk8_init(void); +extern int agp_amd64_init(void); static int __init pci_iommu_init(void) { @@ -690,7 +690,7 @@ static int __init pci_iommu_init(void) /* Makefile puts PCI initialization via subsys_initcall first. */ /* Add other K8 AGP bridge drivers here */ no_agp = no_agp || - (agp_amdk8_init() < 0) || + (agp_amd64_init() < 0) || (agp_copy_info(&info) < 0); #endif diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7358eed7a348..3e30720a167c 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -63,8 +63,7 @@ config AGP_AMD You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. -# RED-PEN this option is misnamed, it's not 8151 specific -config AGP_AMD_8151 +config AGP_AMD64 tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU depends on AGP && X86 default y if GART_IOMMU diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index b537a8394cf1..16194948cc54 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_AGP) += agpgart.o obj-$(CONFIG_AGP_ALI) += ali-agp.o obj-$(CONFIG_AGP_ATI) += ati-agp.o obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o -obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o +obj-$(CONFIG_AGP_AMD64) += amd64-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c deleted file mode 100644 index d147b09056bc..000000000000 --- a/drivers/char/agp/amd-k8-agp.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright 2001-2003 SuSE Labs. - * Distributed under the GNU public license, v2. - * - * This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge. - * It also includes support for the AMD 8151 AGP bridge, - * although it doesn't actually do much, as all the real - * work is done in the northbridge(s). - */ - -#include -#include -#include -#include -#include "agp.h" - -/* Will need to be increased if hammer ever goes >8-way. */ -#ifdef CONFIG_SMP -#define MAX_HAMMER_GARTS 8 -#else -#define MAX_HAMMER_GARTS 1 -#endif - -/* PTE bits. */ -#define GPTE_VALID 1 -#define GPTE_COHERENT 2 - -/* Aperture control register bits. */ -#define GARTEN 1<<0 -#define DISGARTCPU 1<<4 -#define DISGARTIO 1<<5 - -/* GART cache control register bits. */ -#define INVGART 1<<0 -#define GARTPTEERR 1<<1 - -static int nr_garts; -static struct pci_dev * hammers[MAX_HAMMER_GARTS]; - -static int __initdata agp_try_unsupported; - -static int gart_iterator; -#define for_each_nb() for(gart_iterator=0;gart_iteratortype != 0) - return -EINVAL; - - /* Make sure we can fit the range in the gatt table. */ - /* FIXME: could wrap */ - if (((unsigned long)pg_start + mem->page_count) > num_entries) - return -EINVAL; - - j = pg_start; - - /* gatt table should be empty. */ - while (j < (pg_start + mem->page_count)) { - if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) - return -EBUSY; - j++; - } - - if (mem->is_flushed == FALSE) { - global_cache_flush(); - mem->is_flushed = TRUE; - } - - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type); - - BUG_ON(tmp & 0xffffff0000000ffc); - pte = (tmp & 0x000000ff00000000) >> 28; - pte |=(tmp & 0x00000000fffff000); - pte |= GPTE_VALID | GPTE_COHERENT; - - agp_bridge->gatt_table[j] = pte; - } - amd_x86_64_tlbflush(mem); - return 0; -} - -/* - * This hack alters the order element according - * to the size of a long. It sucks. I totally disown this, even - * though it does appear to work for the most part. - */ -static struct aper_size_info_32 x86_64_aperture_sizes[7] = -{ - {32, 8192, 3+(sizeof(long)/8), 0 }, - {64, 16384, 4+(sizeof(long)/8), 1<<1 }, - {128, 32768, 5+(sizeof(long)/8), 1<<2 }, - {256, 65536, 6+(sizeof(long)/8), 1<<1 | 1<<2 }, - {512, 131072, 7+(sizeof(long)/8), 1<<3 }, - {1024, 262144, 8+(sizeof(long)/8), 1<<1 | 1<<3}, - {2048, 524288, 9+(sizeof(long)/8), 1<<2 | 1<<3} -}; - - -/* - * Get the current Aperture size from the x86-64. - * Note, that there may be multiple x86-64's, but we just return - * the value from the first one we find. The set_size functions - * keep the rest coherent anyway. Or at least should do. - */ -static int amd_x86_64_fetch_size(void) -{ - struct pci_dev *dev; - int i; - u32 temp; - struct aper_size_info_32 *values; - - dev = hammers[0]; - if (dev==NULL) - return 0; - - pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &temp); - temp = (temp & 0xe); - values = A_SIZE_32(x86_64_aperture_sizes); - - for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { - if (temp == values[i].size_value) { - agp_bridge->previous_size = - agp_bridge->current_size = (void *) (values + i); - - agp_bridge->aperture_size_idx = i; - return values[i].size; - } - } - return 0; -} - -/* - * In a multiprocessor x86-64 system, this function gets - * called once for each CPU. - */ -static u64 amd_x86_64_configure (struct pci_dev *hammer, u64 gatt_table) -{ - u64 aperturebase; - u32 tmp; - u64 addr, aper_base; - - /* Address to map to */ - pci_read_config_dword (hammer, AMD64_GARTAPERTUREBASE, &tmp); - aperturebase = tmp << 25; - aper_base = (aperturebase & PCI_BASE_ADDRESS_MEM_MASK); - - /* address of the mappings table */ - addr = (u64) gatt_table; - addr >>= 12; - tmp = (u32) addr<<4; - tmp &= ~0xf; - pci_write_config_dword (hammer, AMD64_GARTTABLEBASE, tmp); - - /* Enable GART translation for this hammer. */ - pci_read_config_dword(hammer, AMD64_GARTAPERTURECTL, &tmp); - tmp |= GARTEN; - tmp &= ~(DISGARTCPU | DISGARTIO); - pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); - - /* keep CPU's coherent. */ - flush_x86_64_tlb (hammer); - - return aper_base; -} - - -static struct aper_size_info_32 amd_8151_sizes[7] = -{ - {2048, 524288, 9, 0x00000000 }, /* 0 0 0 0 0 0 */ - {1024, 262144, 8, 0x00000400 }, /* 1 0 0 0 0 0 */ - {512, 131072, 7, 0x00000600 }, /* 1 1 0 0 0 0 */ - {256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */ - {128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */ - {64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */ - {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */ -}; - -static int amd_8151_configure(void) -{ - unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); - - /* Configure AGP regs in each x86-64 host bridge. */ - for_each_nb() { - agp_bridge->gart_bus_addr = - amd_x86_64_configure(hammers[gart_iterator],gatt_bus); - } - return 0; -} - - -static void amd_8151_cleanup(void) -{ - u32 tmp; - - for_each_nb() { - /* disable gart translation */ - pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); - tmp &= ~AMD64_GARTEN; - pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp); - } -} - - -struct agp_bridge_driver amd_8151_driver = { - .owner = THIS_MODULE, - .aperture_sizes = amd_8151_sizes, - .size_type = U32_APER_SIZE, - .num_aperture_sizes = 7, - .configure = amd_8151_configure, - .fetch_size = amd_x86_64_fetch_size, - .cleanup = amd_8151_cleanup, - .tlb_flush = amd_x86_64_tlbflush, - .mask_memory = agp_generic_mask_memory, - .masks = NULL, - .agp_enable = agp_generic_enable, - .cache_flush = global_cache_flush, - .create_gatt_table = agp_generic_create_gatt_table, - .free_gatt_table = agp_generic_free_gatt_table, - .insert_memory = x86_64_insert_memory, - .remove_memory = agp_generic_remove_memory, - .alloc_by_type = agp_generic_alloc_by_type, - .free_by_type = agp_generic_free_by_type, - .agp_alloc_page = agp_generic_alloc_page, - .agp_destroy_page = agp_generic_destroy_page, -}; - -/* Some basic sanity checks for the aperture. */ -static int __init aperture_valid(u64 aper, u32 size) -{ - static int not_first_call; - u32 pfn, c; - if (aper == 0) { - printk(KERN_ERR "No aperture\n"); - return 0; - } - if (size < 32*1024*1024) { - printk(KERN_ERR "Aperture too small (%d MB)\n", size>>20); - return 0; - } - if (aper + size > 0xffffffff) { - printk(KERN_ERR "Aperture out of bounds\n"); - return 0; - } - pfn = aper >> PAGE_SHIFT; - for (c = 0; c < size/PAGE_SIZE; c++) { - if (!pfn_valid(pfn + c)) - break; - if (!PageReserved(pfn_to_page(pfn + c))) { - printk(KERN_ERR "Aperture pointing to RAM\n"); - return 0; - } - } - - /* Request the Aperture. This catches cases when someone else - already put a mapping in there - happens with some very broken BIOS - - Maybe better to use pci_assign_resource/pci_enable_device instead trusting - the bridges? */ - if (!not_first_call && request_mem_region(aper, size, "aperture") < 0) { - printk(KERN_ERR "Aperture conflicts with PCI mapping.\n"); - return 0; - } - - not_first_call = 1; - return 1; -} - -/* - * W*s centric BIOS sometimes only set up the aperture in the AGP - * bridge, not the northbridge. On AMD64 this is handled early - * in aperture.c, but when GART_IOMMU is not enabled or we run - * on a 32bit kernel this needs to be redone. - * Unfortunately it is impossible to fix the aperture here because it's too late - * to allocate that much memory. But at least error out cleanly instead of - * crashing. - */ -static __init int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, - u16 cap) -{ - u32 aper_low, aper_hi; - u64 aper, nb_aper; - int order = 0; - u32 nb_order, nb_base; - u16 apsize; - - pci_read_config_dword(nb, 0x90, &nb_order); - nb_order = (nb_order >> 1) & 7; - pci_read_config_dword(nb, 0x94, &nb_base); - nb_aper = nb_base << 25; - if (aperture_valid(nb_aper, (32*1024*1024)<> 25); - - return 0; -} - -static __init int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) -{ - struct pci_dev *loop_dev = NULL; - int i = 0; - - /* cache pci_devs of northbridges. */ - while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) - != NULL) { - if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { - printk("No usable aperture found.\n"); -#ifdef __x86_64__ - /* should port this to i386 */ - printk("Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); -#endif - return -1; - } - hammers[i++] = loop_dev; - nr_garts = i; - if (i == MAX_HAMMER_GARTS) { - printk(KERN_INFO "Too many northbridges for AGP\n"); - return -1; - } - } - return i == 0 ? -1 : 0; -} - -static int __init agp_amdk8_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct agp_bridge_data *bridge; - u8 rev_id; - u8 cap_ptr; - char *revstring=" "; - - cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); - if (!cap_ptr) - return -ENODEV; - - /* Could check for AGPv3 here */ - - bridge = agp_alloc_bridge(); - if (!bridge) - return -ENOMEM; - - if (pdev->vendor == PCI_VENDOR_ID_AMD && - pdev->device == PCI_DEVICE_ID_AMD_8151_0) { - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); - switch (rev_id) { - case 0x01: revstring="A0"; - break; - case 0x02: revstring="A1"; - break; - case 0x11: revstring="B0"; - break; - case 0x12: revstring="B1"; - break; - case 0x13: revstring="B2"; - break; - default: revstring="??"; - break; - } - printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); - /* - * Work around errata. - * Chips before B2 stepping incorrectly reporting v3.5 - */ - if (rev_id < 0x13) { - printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); - bridge->major_version = 3; - bridge->minor_version = 0; - } - } else { - printk(KERN_INFO PFX "Detected AGP bridge %x\n", - pdev->devfn); - } - - bridge->driver = &amd_8151_driver; - bridge->dev = pdev; - bridge->capndx = cap_ptr; - - /* Fill in the mode register */ - pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); - - if (cache_nbs(pdev, cap_ptr) == -1) { - agp_put_bridge(bridge); - return -ENODEV; - } - - pci_set_drvdata(pdev, bridge); - return agp_add_bridge(bridge); -} - -static void __devexit agp_amdk8_remove(struct pci_dev *pdev) -{ - struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - - release_mem_region(virt_to_phys(bridge->gatt_table_real), - x86_64_aperture_sizes[bridge->aperture_size_idx].size); - agp_remove_bridge(bridge); - agp_put_bridge(bridge); -} - -static struct pci_device_id agp_amdk8_pci_table[] = { - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8151_0, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - /* VIA K8T800 */ - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8385_0, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - /* VIA K8M800 / K8N800 */ - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8380_0, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_755, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } -}; - -MODULE_DEVICE_TABLE(pci, agp_amdk8_pci_table); - -static struct pci_driver agp_amdk8_pci_driver = { - .name = "agpgart-amd-k8", - .id_table = agp_amdk8_pci_table, - .probe = agp_amdk8_probe, - .remove = agp_amdk8_remove, -}; - - -/* Not static due to IOMMU code calling it early. */ -int __init agp_amdk8_init(void) -{ - int err = 0; - if (agp_off) - return -EINVAL; - if (pci_module_init(&agp_amdk8_pci_driver) == 0) { - struct pci_dev *dev; - if (!agp_try_unsupported && !agp_try_unsupported_boot) { - printk(KERN_INFO "No supported AGP bridge found.\n"); -#ifdef MODULE - printk(KERN_INFO "You can try agp_try_unsupported=1\n"); -#else - printk(KERN_INFO "You can boot with agp=try_unsupported\n"); -#endif - return -ENODEV; - } - - /* First check that we have at least one K8 NB */ - if (!pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL)) - return -ENODEV; - - /* Look for any AGP bridge */ - dev = NULL; - err = -ENODEV; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) { - if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) - continue; - /* Only one bridge supported right now */ - if (agp_amdk8_probe(dev, NULL) == 0) { - err = 0; - break; - } - } - } - return err; -} - -static void __exit agp_amdk8_cleanup(void) -{ - pci_unregister_driver(&agp_amdk8_pci_driver); -} - -/* On x86-64 the PCI driver needs to initialize this driver early - for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_GART_IOMMU -module_init(agp_amdk8_init); -module_exit(agp_amdk8_cleanup); -#endif - -MODULE_AUTHOR("Dave Jones , Andi Kleen"); -MODULE_PARM(agp_try_unsupported, "1i"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c new file mode 100644 index 000000000000..e351e2966e35 --- /dev/null +++ b/drivers/char/agp/amd64-agp.c @@ -0,0 +1,544 @@ +/* + * Copyright 2001-2003 SuSE Labs. + * Distributed under the GNU public license, v2. + * + * This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge. + * It also includes support for the AMD 8151 AGP bridge, + * although it doesn't actually do much, as all the real + * work is done in the northbridge(s). + */ + +#include +#include +#include +#include +#include "agp.h" + +/* Will need to be increased if AMD64 ever goes >8-way. */ +#ifdef CONFIG_SMP +#define MAX_HAMMER_GARTS 8 +#else +#define MAX_HAMMER_GARTS 1 +#endif + +/* PTE bits. */ +#define GPTE_VALID 1 +#define GPTE_COHERENT 2 + +/* Aperture control register bits. */ +#define GARTEN 1<<0 +#define DISGARTCPU 1<<4 +#define DISGARTIO 1<<5 + +/* GART cache control register bits. */ +#define INVGART 1<<0 +#define GARTPTEERR 1<<1 + +static int nr_garts; +static struct pci_dev * hammers[MAX_HAMMER_GARTS]; + +static int __initdata agp_try_unsupported; + +static int gart_iterator; +#define for_each_nb() for(gart_iterator=0;gart_iteratortype != 0) + return -EINVAL; + + /* Make sure we can fit the range in the gatt table. */ + /* FIXME: could wrap */ + if (((unsigned long)pg_start + mem->page_count) > num_entries) + return -EINVAL; + + j = pg_start; + + /* gatt table should be empty. */ + while (j < (pg_start + mem->page_count)) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) + return -EBUSY; + j++; + } + + if (mem->is_flushed == FALSE) { + global_cache_flush(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type); + + BUG_ON(tmp & 0xffffff0000000ffc); + pte = (tmp & 0x000000ff00000000) >> 28; + pte |=(tmp & 0x00000000fffff000); + pte |= GPTE_VALID | GPTE_COHERENT; + + agp_bridge->gatt_table[j] = pte; + } + amd64_tlbflush(mem); + return 0; +} + +/* + * This hack alters the order element according + * to the size of a long. It sucks. I totally disown this, even + * though it does appear to work for the most part. + */ +static struct aper_size_info_32 amd64_aperture_sizes[7] = +{ + {32, 8192, 3+(sizeof(long)/8), 0 }, + {64, 16384, 4+(sizeof(long)/8), 1<<1 }, + {128, 32768, 5+(sizeof(long)/8), 1<<2 }, + {256, 65536, 6+(sizeof(long)/8), 1<<1 | 1<<2 }, + {512, 131072, 7+(sizeof(long)/8), 1<<3 }, + {1024, 262144, 8+(sizeof(long)/8), 1<<1 | 1<<3}, + {2048, 524288, 9+(sizeof(long)/8), 1<<2 | 1<<3} +}; + + +/* + * Get the current Aperture size from the x86-64. + * Note, that there may be multiple x86-64's, but we just return + * the value from the first one we find. The set_size functions + * keep the rest coherent anyway. Or at least should do. + */ +static int amd64_fetch_size(void) +{ + struct pci_dev *dev; + int i; + u32 temp; + struct aper_size_info_32 *values; + + dev = hammers[0]; + if (dev==NULL) + return 0; + + pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &temp); + temp = (temp & 0xe); + values = A_SIZE_32(amd64_aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + return 0; +} + +/* + * In a multiprocessor x86-64 system, this function gets + * called once for each CPU. + */ +static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table) +{ + u64 aperturebase; + u32 tmp; + u64 addr, aper_base; + + /* Address to map to */ + pci_read_config_dword (hammer, AMD64_GARTAPERTUREBASE, &tmp); + aperturebase = tmp << 25; + aper_base = (aperturebase & PCI_BASE_ADDRESS_MEM_MASK); + + /* address of the mappings table */ + addr = (u64) gatt_table; + addr >>= 12; + tmp = (u32) addr<<4; + tmp &= ~0xf; + pci_write_config_dword (hammer, AMD64_GARTTABLEBASE, tmp); + + /* Enable GART translation for this hammer. */ + pci_read_config_dword(hammer, AMD64_GARTAPERTURECTL, &tmp); + tmp |= GARTEN; + tmp &= ~(DISGARTCPU | DISGARTIO); + pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); + + /* keep CPU's coherent. */ + flush_amd64_tlb (hammer); + + return aper_base; +} + + +static struct aper_size_info_32 amd_8151_sizes[7] = +{ + {2048, 524288, 9, 0x00000000 }, /* 0 0 0 0 0 0 */ + {1024, 262144, 8, 0x00000400 }, /* 1 0 0 0 0 0 */ + {512, 131072, 7, 0x00000600 }, /* 1 1 0 0 0 0 */ + {256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */ + {128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */ + {64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */ + {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */ +}; + +static int amd_8151_configure(void) +{ + unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); + + /* Configure AGP regs in each x86-64 host bridge. */ + for_each_nb() { + agp_bridge->gart_bus_addr = + amd64_configure(hammers[gart_iterator],gatt_bus); + } + return 0; +} + + +static void amd64_cleanup(void) +{ + u32 tmp; + + for_each_nb() { + /* disable gart translation */ + pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); + tmp &= ~AMD64_GARTEN; + pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp); + } +} + + +struct agp_bridge_driver amd_8151_driver = { + .owner = THIS_MODULE, + .aperture_sizes = amd_8151_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = amd_8151_configure, + .fetch_size = amd64_fetch_size, + .cleanup = amd64_cleanup, + .tlb_flush = amd64_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = amd64_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + +/* Some basic sanity checks for the aperture. */ +static int __init aperture_valid(u64 aper, u32 size) +{ + static int not_first_call; + u32 pfn, c; + if (aper == 0) { + printk(KERN_ERR "No aperture\n"); + return 0; + } + if (size < 32*1024*1024) { + printk(KERN_ERR "Aperture too small (%d MB)\n", size>>20); + return 0; + } + if (aper + size > 0xffffffff) { + printk(KERN_ERR "Aperture out of bounds\n"); + return 0; + } + pfn = aper >> PAGE_SHIFT; + for (c = 0; c < size/PAGE_SIZE; c++) { + if (!pfn_valid(pfn + c)) + break; + if (!PageReserved(pfn_to_page(pfn + c))) { + printk(KERN_ERR "Aperture pointing to RAM\n"); + return 0; + } + } + + /* Request the Aperture. This catches cases when someone else + already put a mapping in there - happens with some very broken BIOS + + Maybe better to use pci_assign_resource/pci_enable_device instead trusting + the bridges? */ + if (!not_first_call && request_mem_region(aper, size, "aperture") < 0) { + printk(KERN_ERR "Aperture conflicts with PCI mapping.\n"); + return 0; + } + + not_first_call = 1; + return 1; +} + +/* + * W*s centric BIOS sometimes only set up the aperture in the AGP + * bridge, not the northbridge. On AMD64 this is handled early + * in aperture.c, but when GART_IOMMU is not enabled or we run + * on a 32bit kernel this needs to be redone. + * Unfortunately it is impossible to fix the aperture here because it's too late + * to allocate that much memory. But at least error out cleanly instead of + * crashing. + */ +static __init int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, + u16 cap) +{ + u32 aper_low, aper_hi; + u64 aper, nb_aper; + int order = 0; + u32 nb_order, nb_base; + u16 apsize; + + pci_read_config_dword(nb, 0x90, &nb_order); + nb_order = (nb_order >> 1) & 7; + pci_read_config_dword(nb, 0x94, &nb_base); + nb_aper = nb_base << 25; + if (aperture_valid(nb_aper, (32*1024*1024)<> 25); + + return 0; +} + +static __init int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) +{ + struct pci_dev *loop_dev = NULL; + int i = 0; + + /* cache pci_devs of northbridges. */ + while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) + != NULL) { + if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { + printk("No usable aperture found.\n"); +#ifdef __x86_64__ + /* should port this to i386 */ + printk("Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); +#endif + return -1; + } + hammers[i++] = loop_dev; + nr_garts = i; + if (i == MAX_HAMMER_GARTS) { + printk(KERN_INFO "Too many northbridges for AGP\n"); + return -1; + } + } + return i == 0 ? -1 : 0; +} + +static int __init agp_amd64_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_bridge_data *bridge; + u8 rev_id; + u8 cap_ptr; + char *revstring=" "; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* Could check for AGPv3 here */ + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + if (pdev->vendor == PCI_VENDOR_ID_AMD && + pdev->device == PCI_DEVICE_ID_AMD_8151_0) { + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); + switch (rev_id) { + case 0x01: revstring="A0"; + break; + case 0x02: revstring="A1"; + break; + case 0x11: revstring="B0"; + break; + case 0x12: revstring="B1"; + break; + case 0x13: revstring="B2"; + break; + default: revstring="??"; + break; + } + printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); + /* + * Work around errata. + * Chips before B2 stepping incorrectly reporting v3.5 + */ + if (rev_id < 0x13) { + printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); + bridge->major_version = 3; + bridge->minor_version = 0; + } + } else { + printk(KERN_INFO PFX "Detected AGP bridge %x\n", + pdev->devfn); + } + + bridge->driver = &amd_8151_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); + + if (cache_nbs(pdev, cap_ptr) == -1) { + agp_put_bridge(bridge); + return -ENODEV; + } + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_amd64_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + release_mem_region(virt_to_phys(bridge->gatt_table_real), + amd64_aperture_sizes[bridge->aperture_size_idx].size); + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static struct pci_device_id agp_amd64_pci_table[] = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8151_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + /* VIA K8T800 */ + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8385_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + /* VIA K8M800 / K8N800 */ + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8380_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_755, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); + +static struct pci_driver agp_amd64_pci_driver = { + .name = "agpgart-amd64", + .id_table = agp_amd64_pci_table, + .probe = agp_amd64_probe, + .remove = agp_amd64_remove, +}; + + +/* Not static due to IOMMU code calling it early. */ +int __init agp_amd64_init(void) +{ + int err = 0; + if (agp_off) + return -EINVAL; + if (pci_module_init(&agp_amd64_pci_driver) == 0) { + struct pci_dev *dev; + if (!agp_try_unsupported && !agp_try_unsupported_boot) { + printk(KERN_INFO "No supported AGP bridge found.\n"); +#ifdef MODULE + printk(KERN_INFO "You can try agp_try_unsupported=1\n"); +#else + printk(KERN_INFO "You can boot with agp=try_unsupported\n"); +#endif + return -ENODEV; + } + + /* First check that we have at least one AMD64 NB */ + if (!pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL)) + return -ENODEV; + + /* Look for any AGP bridge */ + dev = NULL; + err = -ENODEV; + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) { + if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) + continue; + /* Only one bridge supported right now */ + if (agp_amd64_probe(dev, NULL) == 0) { + err = 0; + break; + } + } + } + return err; +} + +static void __exit agp_amd64_cleanup(void) +{ + pci_unregister_driver(&agp_amd64_pci_driver); +} + +/* On AMD64 the PCI driver needs to initialize this driver early + for the IOMMU, so it has to be called via a backdoor. */ +#ifndef CONFIG_GART_IOMMU +module_init(agp_amd64_init); +module_exit(agp_amd64_cleanup); +#endif + +MODULE_AUTHOR("Dave Jones , Andi Kleen"); +MODULE_PARM(agp_try_unsupported, "1i"); +MODULE_LICENSE("GPL and additional rights"); -- cgit v1.2.3 From 54eca890d496686c5fcf5e09659d581a49040e93 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Tue, 2 Sep 2003 00:24:38 -0700 Subject: [SCTP] Convert sctp_param2sockaddr() and sockaddr2sctp_addr() to address family specific routines af->from_addr_parm() and af->to_addr_param() respectively. --- include/net/sctp/sctp.h | 13 ++++ include/net/sctp/sm.h | 6 -- include/net/sctp/structs.h | 166 +++++++++++++++++++++++---------------------- net/sctp/bind_addr.c | 37 +++++----- net/sctp/input.c | 8 ++- net/sctp/ipv6.c | 29 ++++++++ net/sctp/protocol.c | 27 ++++++++ net/sctp/sm_make_chunk.c | 120 +++----------------------------- net/sctp/sm_statefuns.c | 3 +- 9 files changed, 191 insertions(+), 218 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index a456d5a99d37..3f21f1985699 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -533,6 +533,19 @@ static inline int ipver2af(__u8 ipver) }; } +/* Convert from an address parameter type to an address family. */ +static inline int param_type2af(__u16 type) +{ + switch (type) { + case SCTP_PARAM_IPV4_ADDRESS: + return AF_INET; + case SCTP_PARAM_IPV6_ADDRESS: + return AF_INET6; + default: + return 0; + }; +} + /* Perform some sanity checks. */ static inline int sctp_sanity_check(void) { diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 40cb876aaf96..3eb9c18df0c5 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -334,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); -/* 4th level prototypes */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *, - __u16 port, int iif); -int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *); -int sockaddr2sctp_addr(const union sctp_addr *, union sctp_addr_param *); - /* Extern declarations for major data structures. */ const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); extern const sctp_sm_table_entry_t diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d6199d3a2081..7ba32701be00 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -218,86 +218,6 @@ extern struct sctp_globals { #define sctp_local_addr_list (sctp_globals.local_addr_list) #define sctp_local_addr_lock (sctp_globals.local_addr_lock) -/* - * Pointers to address related SCTP functions. - * (i.e. things that depend on the address family.) - */ -struct sctp_af { - int (*sctp_xmit) (struct sk_buff *skb, - struct sctp_transport *, - int ipfragok); - int (*setsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int optlen); - int (*getsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*get_saddr) (struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*copy_addrlist) (struct list_head *, - struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - unsigned short port); - int (*cmp_addr) (const union sctp_addr *addr1, - const union sctp_addr *addr2); - void (*addr_copy) (union sctp_addr *dst, - union sctp_addr *src); - void (*from_skb) (union sctp_addr *, - struct sk_buff *skb, - int saddr); - void (*from_sk) (union sctp_addr *, - struct sock *sk); - void (*to_sk_saddr) (union sctp_addr *, - struct sock *sk); - void (*to_sk_daddr) (union sctp_addr *, - struct sock *sk); - int (*addr_valid) (union sctp_addr *, - struct sctp_opt *); - sctp_scope_t (*scope) (union sctp_addr *); - void (*inaddr_any) (union sctp_addr *, unsigned short); - int (*is_any) (const union sctp_addr *); - int (*available) (union sctp_addr *, - struct sctp_opt *); - int (*skb_iif) (const struct sk_buff *sk); - int (*is_ce) (const struct sk_buff *sk); - void (*seq_dump_addr)(struct seq_file *seq, - union sctp_addr *addr); - __u16 net_header_len; - int sockaddr_len; - sa_family_t sa_family; - struct list_head list; -}; - -struct sctp_af *sctp_get_af_specific(sa_family_t); -int sctp_register_af(struct sctp_af *); - -/* Protocol family functions. */ -struct sctp_pf { - void (*event_msgname)(struct sctp_ulpevent *, char *, int *); - void (*skb_msgname) (struct sk_buff *, char *, int *); - int (*af_supported) (sa_family_t, struct sctp_opt *); - int (*cmp_addr) (const union sctp_addr *, - const union sctp_addr *, - struct sctp_opt *); - int (*bind_verify) (struct sctp_opt *, union sctp_addr *); - int (*send_verify) (struct sctp_opt *, union sctp_addr *); - int (*supported_addrs)(const struct sctp_opt *, __u16 *); - struct sock *(*create_accept_sk) (struct sock *sk, - struct sctp_association *asoc); - void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); - struct sctp_af *af; -}; - /* SCTP Socket type: UDP or TCP style. */ typedef enum { SCTP_SOCKET_UDP = 0, @@ -489,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) return stream->ssn[id]++; } +/* + * Pointers to address related SCTP functions. + * (i.e. things that depend on the address family.) + */ +struct sctp_af { + int (*sctp_xmit) (struct sk_buff *skb, + struct sctp_transport *, + int ipfragok); + int (*setsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int optlen); + int (*getsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int *optlen); + struct dst_entry *(*get_dst) (struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*get_saddr) (struct sctp_association *asoc, + struct dst_entry *dst, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*copy_addrlist) (struct list_head *, + struct net_device *); + void (*dst_saddr) (union sctp_addr *saddr, + struct dst_entry *dst, + unsigned short port); + int (*cmp_addr) (const union sctp_addr *addr1, + const union sctp_addr *addr2); + void (*addr_copy) (union sctp_addr *dst, + union sctp_addr *src); + void (*from_skb) (union sctp_addr *, + struct sk_buff *skb, + int saddr); + void (*from_sk) (union sctp_addr *, + struct sock *sk); + void (*to_sk_saddr) (union sctp_addr *, + struct sock *sk); + void (*to_sk_daddr) (union sctp_addr *, + struct sock *sk); + void (*from_addr_param) (union sctp_addr *, + union sctp_addr_param *, + __u16 port, int iif); + int (*to_addr_param) (const union sctp_addr *, + union sctp_addr_param *); + int (*addr_valid) (union sctp_addr *, + struct sctp_opt *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); + int (*available) (union sctp_addr *, + struct sctp_opt *); + int (*skb_iif) (const struct sk_buff *sk); + int (*is_ce) (const struct sk_buff *sk); + void (*seq_dump_addr)(struct seq_file *seq, + union sctp_addr *addr); + __u16 net_header_len; + int sockaddr_len; + sa_family_t sa_family; + struct list_head list; +}; + +struct sctp_af *sctp_get_af_specific(sa_family_t); +int sctp_register_af(struct sctp_af *); + +/* Protocol family functions. */ +struct sctp_pf { + void (*event_msgname)(struct sctp_ulpevent *, char *, int *); + void (*skb_msgname) (struct sk_buff *, char *, int *); + int (*af_supported) (sa_family_t, struct sctp_opt *); + int (*cmp_addr) (const union sctp_addr *, + const union sctp_addr *, + struct sctp_opt *); + int (*bind_verify) (struct sctp_opt *, union sctp_addr *); + int (*send_verify) (struct sctp_opt *, union sctp_addr *); + int (*supported_addrs)(const struct sctp_opt *, __u16 *); + struct sock *(*create_accept_sk) (struct sock *sk, + struct sctp_association *asoc); + void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); + struct sctp_af *af; +}; + + /* Structure to track chunk fragments that have been acked, but peer * fragments of the same message have not. */ diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 58d6a3bb7c3e..fa51ddefa3e0 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -225,6 +225,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, struct list_head *pos; addrparms_len = 0; len = 0; + struct sctp_af *af; /* Allocate enough memory at once. */ list_for_each(pos, &bp->address_list) { @@ -247,7 +248,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - len = sockaddr2sctp_addr(&addr->a, &rawaddr); + af = sctp_get_af_specific(addr->a.v4.sin_family); + len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; @@ -270,34 +272,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, union sctp_addr addr; int retval = 0; int len; + struct sctp_af *af; /* Convert the raw address to standard address format */ while (addrs_len) { param = (struct sctp_paramhdr *)raw_addr_list; rawaddr = (union sctp_addr_param *)raw_addr_list; - switch (param->type) { - case SCTP_PARAM_IPV4_ADDRESS: - case SCTP_PARAM_IPV6_ADDRESS: - sctp_param2sockaddr(&addr, rawaddr, port, 0); - retval = sctp_add_bind_addr(bp, &addr, gfp); - if (retval) { - /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break;; - } - len = ntohs(param->length); - addrs_len -= len; - raw_addr_list += len; - break; - default: - /* Corrupted raw addr list! */ + af = sctp_get_af_specific(param_type2af(param->type)); + if (unlikely(!af)) { retval = -EINVAL; sctp_bind_addr_clean(bp); break; } - if (retval) - break; + + af->from_addr_param(&addr, rawaddr, port, 0); + retval = sctp_add_bind_addr(bp, &addr, gfp); + if (retval) { + /* Can't finish building the list, clean up. */ + sctp_bind_addr_clean(bp); + break;; + } + + len = ntohs(param->length); + addrs_len -= len; + raw_addr_list += len; } return retval; diff --git a/net/sctp/input.c b/net/sctp/input.c index 2c62c2171f6a..cc3e9314dd91 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, union sctp_params params; sctp_init_chunk_t *init; struct sctp_transport *transport; + struct sctp_af *af; ch = (sctp_chunkhdr_t *) skb->data; @@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, sctp_walk_params(params, init, init_hdr.params) { /* Note: Ignoring hostname addresses. */ - if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && - (SCTP_PARAM_IPV6_ADDRESS != params.p->type)) + af = sctp_get_af_specific(param_type2af(params.p->type)); + if (!af) continue; - sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); + af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3bce456b895f..32ec1d5176ff 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) } } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v6_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo = 0; /* BUG */ + ipv6_addr_copy(&addr->v6.sin6_addr, ¶m->v6.addr); + addr->v6.sin6_scope_id = iif; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v6_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv6addr_param_t); + + param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; + param->v6.param_hdr.length = ntohs(length); + ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, unsigned short port) @@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = { .from_sk = sctp_v6_from_sk, .to_sk_saddr = sctp_v6_to_sk_saddr, .to_sk_daddr = sctp_v6_to_sk_daddr, + .from_addr_param = sctp_v6_from_addr_param, + .to_addr_param = sctp_v6_to_addr_param, .dst_saddr = sctp_v6_dst_saddr, .cmp_addr = sctp_v6_cmp_addr, .scope = sctp_v6_scope, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 727f237b1475..986460afaa6b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr; } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v4_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_port = port; + addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v4_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv4addr_param_t); + + param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; + param->v4.param_hdr.length = ntohs(length); + param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, unsigned short port) @@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = { .from_sk = sctp_v4_from_sk, .to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_daddr = sctp_v4_to_sk_daddr, + .from_addr_param= sctp_v4_from_addr_param, + .to_addr_param = sctp_v4_to_addr_param, .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9f32aa219158..44ee598cbe03 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1214,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sctp_association *asoc; struct sk_buff *skb; sctp_scope_t scope; + struct sctp_af *af; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1223,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, asoc->temp = 1; skb = chunk->skb; /* Create an entry for the source address of the packet. */ - /* FIXME: Use the af specific helpers. */ - switch (skb->nh.iph->version) { - case 4: - asoc->c.peer_addr.v4.sin_family = AF_INET; - asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr; - break; - - case 6: - asoc->c.peer_addr.v6.sin6_family = AF_INET6; - asoc->c.peer_addr.v6.sin6_port - = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ - asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr; - asoc->c.peer_addr.v6.sin6_scope_id = - ((struct inet6_skb_parm *)skb->cb)->iif; - break; - - default: - /* Yikes! I never heard of this kind of address. */ + af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); + if (unlikely(!af)) goto fail; - }; - + af->from_skb(&asoc->c.peer_addr, skb, 1); nodata: return asoc; @@ -1883,6 +1865,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, int retval = 1; sctp_scope_t scope; time_t stale; + struct sctp_af *af; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -1894,7 +1877,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, break; /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: - sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0); + af = sctp_get_af_specific(param_type2af(param.p->type)); + af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); scope = sctp_scope(peer_addr); if (sctp_in_scope(&addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp)) @@ -2006,90 +1990,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep) return retval; } -/******************************************************************** - * 4th Level Abstractions - ********************************************************************/ - -/* Convert from an SCTP IP parameter to a union sctp_addr. */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *param, - __u16 port, int iif) -{ - switch(param->v4.param_hdr.type) { - case SCTP_PARAM_IPV4_ADDRESS: - addr->v4.sin_family = AF_INET; - addr->v4.sin_port = port; - addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = port; - addr->v6.sin6_flowinfo = 0; /* BUG */ - addr->v6.sin6_addr = param->v6.addr; - addr->v6.sin6_scope_id = iif; - break; - - default: - SCTP_DEBUG_PRINTK("Illegal address type %d\n", - ntohs(param->v4.param_hdr.type)); - break; - }; -} - -/* Convert an IP address in an SCTP param into a sockaddr_in. */ -/* Returns true if a valid conversion was possible. */ -int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa) -{ - switch (p.p->type) { - case SCTP_PARAM_IPV4_ADDRESS: - sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr); - sa->v4.sin_family = AF_INET; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - *((struct in6_addr *)&sa->v4.sin_addr) - = p.v6->addr; - sa->v4.sin_family = AF_INET6; - break; - - default: - return 0; - }; - - return 1; -} - -/* Convert a sockaddr_in to an IP address in an SCTP param. - * Returns len if a valid conversion was possible. - */ -int sockaddr2sctp_addr(const union sctp_addr *sa, union sctp_addr_param *p) -{ - int len = 0; - - switch (sa->v4.sin_family) { - case AF_INET: - p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; - p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t)); - len = sizeof(sctp_ipv4addr_param_t); - p->v4.addr.s_addr = sa->v4.sin_addr.s_addr; - break; - - case AF_INET6: - p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; - p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t)); - len = sizeof(sctp_ipv6addr_param_t); - p->v6.addr = *(&sa->v6.sin6_addr); - break; - - default: - printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n", - sa->v4.sin_family); - return 0; - }; - - return len; -} - /* * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF) * 0 1 2 3 @@ -2120,8 +2020,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, int length = sizeof(asconf) + vparam_len; union sctp_params addrparam; int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); - addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); if (!addrlen) return NULL; length += addrlen; @@ -2163,8 +2064,9 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, int len = sizeof(param); union sctp_params addrparam; int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); - addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); if (!addrlen) return NULL; len += addrlen; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 531ff1606429..86208c51ba36 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, struct sctp_errhdr *errhdr; struct sctp_endpoint *ep; char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)]; + struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); /* Build the error on the stack. We are way to malloc crazy * throughout the code today. @@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, addrparm = (union sctp_addr_param *)errhdr->variable; /* Copy into a parm format. */ - len = sockaddr2sctp_addr(ssa, addrparm); + len = af->to_addr_param(ssa, addrparm); len += sizeof(sctp_errhdr_t); errhdr->cause = SCTP_ERROR_RESTART; -- cgit v1.2.3 From 74ba685ef4520523ddd4e7aeeb8a37f2533eed49 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 01:07:47 +0100 Subject: [CPUFREQ] Move kernel/cpufreq.c to drivers/cpufreq/cpufreq.c Also remove $Id$ tag. No other code change. --- drivers/cpufreq/Makefile | 3 + drivers/cpufreq/cpufreq.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/Makefile | 1 - kernel/cpufreq.c | 963 ---------------------------------------------- 4 files changed, 966 insertions(+), 964 deletions(-) create mode 100644 drivers/cpufreq/cpufreq.c delete mode 100644 kernel/cpufreq.c diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 85b512348acd..98d532579bf4 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -1,3 +1,6 @@ +# CPUfreq core +obj-$(CONFIG_CPU_FREQ) += cpufreq.o + # CPUfreq governors obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c new file mode 100644 index 000000000000..7f80c321c785 --- /dev/null +++ b/drivers/cpufreq/cpufreq.c @@ -0,0 +1,963 @@ +/* + * linux/kernel/cpufreq.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2003 Dominik Brodowski + * + * $Id: cpufreq.c,v 1.59 2003/01/20 17:31:48 db Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * The "cpufreq driver" - the arch- or hardware-dependend low + * level driver of CPUFreq support, and its spinlock. This lock + * also protects the cpufreq_cpu_data array. + */ +static struct cpufreq_driver *cpufreq_driver; +static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; +static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; + +/* internal prototype */ +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); + + +/** + * Two notifier lists: the "policy" list is involved in the + * validation process for a new CPU frequency policy; the + * "transition" list for kernel code that needs to handle + * changes to devices when the CPU clock speed changes. + * The mutex locks both lists. + */ +static struct notifier_block *cpufreq_policy_notifier_list; +static struct notifier_block *cpufreq_transition_notifier_list; +static DECLARE_RWSEM (cpufreq_notifier_rwsem); + + +static LIST_HEAD(cpufreq_governor_list); +static DECLARE_MUTEX (cpufreq_governor_sem); + +static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) +{ + struct cpufreq_policy *data; + unsigned long flags; + + if (cpu >= NR_CPUS) + goto err_out; + + /* get the cpufreq driver */ + spin_lock_irqsave(&cpufreq_driver_lock, flags); + + if (!cpufreq_driver) + goto err_out_unlock; + + if (!try_module_get(cpufreq_driver->owner)) + goto err_out_unlock; + + + /* get the CPU */ + data = cpufreq_cpu_data[cpu]; + + if (!data) + goto err_out_put_module; + + if (!kobject_get(&data->kobj)) + goto err_out_put_module; + + + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + return data; + + err_out_put_module: + module_put(cpufreq_driver->owner); + err_out_unlock: + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + err_out: + return NULL; +} + +static void cpufreq_cpu_put(struct cpufreq_policy *data) +{ + kobject_put(&data->kobj); + module_put(cpufreq_driver->owner); +} + +/********************************************************************* + * SYSFS INTERFACE * + *********************************************************************/ + +/** + * cpufreq_parse_governor - parse a governor string + */ +int cpufreq_parse_governor (char *str_governor, unsigned int *policy, + struct cpufreq_governor **governor) +{ + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_PERFORMANCE; + return 0; + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_POWERSAVE; + return 0; + } else { + struct cpufreq_governor *t; + down(&cpufreq_governor_sem); + if (!cpufreq_driver || !cpufreq_driver->target) + goto out; + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { + *governor = t; + *policy = CPUFREQ_POLICY_GOVERNOR; + up(&cpufreq_governor_sem); + return 0; + } + } + out: + up(&cpufreq_governor_sem); + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(cpufreq_parse_governor); + + +/* drivers/base/cpu.c */ +extern struct sysdev_class cpu_sysdev_class; + + +/** + * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information + * + * Write out information from cpufreq_driver->policy[cpu]; object must be + * "unsigned int". + */ + +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct cpufreq_policy * policy, char *buf) \ +{ \ + return sprintf (buf, "%u\n", policy->object); \ +} + +show_one(cpuinfo_min_freq, cpuinfo.min_freq); +show_one(cpuinfo_max_freq, cpuinfo.max_freq); +show_one(scaling_min_freq, min); +show_one(scaling_max_freq, max); + +/** + * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access + */ +#define store_one(file_name, object) \ +static ssize_t store_##file_name \ +(struct cpufreq_policy * policy, const char *buf, size_t count) \ +{ \ + unsigned int ret = -EINVAL; \ + struct cpufreq_policy new_policy; \ + \ + ret = cpufreq_get_policy(&new_policy, policy->cpu); \ + if (ret) \ + return -EINVAL; \ + \ + ret = sscanf (buf, "%u", &new_policy.object); \ + if (ret != 1) \ + return -EINVAL; \ + \ + ret = cpufreq_set_policy(&new_policy); \ + \ + return ret ? ret : count; \ +} + +store_one(scaling_min_freq,min); +store_one(scaling_max_freq,max); + +/** + * show_scaling_governor - show the current policy for the specified CPU + */ +static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) +{ + switch (policy->policy) { + case CPUFREQ_POLICY_POWERSAVE: + return sprintf(buf, "powersave\n"); + case CPUFREQ_POLICY_PERFORMANCE: + return sprintf(buf, "performance\n"); + case CPUFREQ_POLICY_GOVERNOR: + return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); + default: + return -EINVAL; + } +} + + +/** + * store_scaling_governor - store policy for the specified CPU + */ +static ssize_t store_scaling_governor (struct cpufreq_policy * policy, + const char *buf, size_t count) +{ + unsigned int ret = -EINVAL; + char str_governor[16]; + struct cpufreq_policy new_policy; + + ret = cpufreq_get_policy(&new_policy, policy->cpu); + if (ret) + return ret; + + ret = sscanf (buf, "%15s", str_governor); + if (ret != 1) + return -EINVAL; + + if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor)) + return -EINVAL; + + ret = cpufreq_set_policy(&new_policy); + + return ret ? ret : count; +} + +/** + * show_scaling_driver - show the cpufreq driver currently loaded + */ +static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) +{ + return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); +} + +/** + * show_scaling_available_governors - show the available CPUfreq governors + */ +static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, + char *buf) +{ + ssize_t i = 0; + struct cpufreq_governor *t; + + i += sprintf(buf, "performance powersave"); + + if (!cpufreq_driver->target) + goto out; + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) + goto out; + i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name); + } + out: + i += sprintf(&buf[i], "\n"); + return i; +} + + +#define define_one_ro(_name) \ +struct freq_attr _name = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = show_##_name, \ +} + +#define define_one_rw(_name) \ +struct freq_attr _name = { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .show = show_##_name, \ + .store = store_##_name, \ +} + +define_one_ro(cpuinfo_min_freq); +define_one_ro(cpuinfo_max_freq); +define_one_ro(scaling_available_governors); +define_one_ro(scaling_driver); +define_one_rw(scaling_min_freq); +define_one_rw(scaling_max_freq); +define_one_rw(scaling_governor); + +static struct attribute * default_attrs[] = { + &cpuinfo_min_freq.attr, + &cpuinfo_max_freq.attr, + &scaling_min_freq.attr, + &scaling_max_freq.attr, + &scaling_governor.attr, + &scaling_driver.attr, + &scaling_available_governors.attr, + NULL +}; + +#define to_policy(k) container_of(k,struct cpufreq_policy,kobj) +#define to_attr(a) container_of(a,struct freq_attr,attr) + +static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) +{ + struct cpufreq_policy * policy = to_policy(kobj); + struct freq_attr * fattr = to_attr(attr); + ssize_t ret; + policy = cpufreq_cpu_get(policy->cpu); + if (!policy) + return -EINVAL; + ret = fattr->show ? fattr->show(policy,buf) : 0; + cpufreq_cpu_put(policy); + return ret; +} + +static ssize_t store(struct kobject * kobj, struct attribute * attr, + const char * buf, size_t count) +{ + struct cpufreq_policy * policy = to_policy(kobj); + struct freq_attr * fattr = to_attr(attr); + ssize_t ret; + policy = cpufreq_cpu_get(policy->cpu); + if (!policy) + return -EINVAL; + ret = fattr->store ? fattr->store(policy,buf,count) : 0; + cpufreq_cpu_put(policy); + return ret; +} + +static void cpufreq_sysfs_release(struct kobject * kobj) +{ + struct cpufreq_policy * policy = to_policy(kobj); + complete(&policy->kobj_unregister); +} + +static struct sysfs_ops sysfs_ops = { + .show = show, + .store = store, +}; + +static struct kobj_type ktype_cpufreq = { + .sysfs_ops = &sysfs_ops, + .default_attrs = default_attrs, + .release = cpufreq_sysfs_release, +}; + + +/** + * cpufreq_add_dev - add a CPU device + * + * Adds the cpufreq interface for a CPU device. + */ +static int cpufreq_add_dev (struct sys_device * sys_dev) +{ + unsigned int cpu = sys_dev->id; + int ret = 0; + struct cpufreq_policy new_policy; + struct cpufreq_policy *policy; + struct freq_attr **drv_attr; + unsigned long flags; + + if (!try_module_get(cpufreq_driver->owner)) + return -EINVAL; + + policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); + if (!policy) + return -ENOMEM; + memset(policy, 0, sizeof(struct cpufreq_policy)); + + policy->cpu = cpu; + init_MUTEX_LOCKED(&policy->lock); + init_completion(&policy->kobj_unregister); + + /* call driver. From then on the cpufreq must be able + * to accept all calls to ->verify and ->setpolicy for this CPU + */ + ret = cpufreq_driver->init(policy); + if (ret) + goto err_out; + + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + + /* prepare interface data */ + policy->kobj.parent = &sys_dev->kobj; + policy->kobj.ktype = &ktype_cpufreq; + strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); + + ret = kobject_register(&policy->kobj); + if (ret) + goto err_out; + + /* set up files for this cpu device */ + drv_attr = cpufreq_driver->attr; + while ((drv_attr) && (*drv_attr)) { + sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); + drv_attr++; + } + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_cpu_data[cpu] = policy; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + up(&policy->lock); + + /* set default policy */ + ret = cpufreq_set_policy(&new_policy); + if (ret) + goto err_out_unregister; + + module_put(cpufreq_driver->owner); + return 0; + + + err_out_unregister: + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_cpu_data[cpu] = NULL; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + kobject_unregister(&policy->kobj); + wait_for_completion(&policy->kobj_unregister); + + err_out: + kfree(policy); + module_put(cpufreq_driver->owner); + return ret; +} + + +/** + * cpufreq_remove_dev - remove a CPU device + * + * Removes the cpufreq interface for a CPU device. + */ +static int cpufreq_remove_dev (struct sys_device * sys_dev) +{ + unsigned int cpu = sys_dev->id; + unsigned long flags; + struct cpufreq_policy *data; + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + data = cpufreq_cpu_data[cpu]; + + if (!data) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + return -EINVAL; + } + cpufreq_cpu_data[cpu] = NULL; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + if (!kobject_get(&data->kobj)) + return -EFAULT; + + kobject_unregister(&data->kobj); + + kobject_put(&data->kobj); + + /* we need to make sure that the underlying kobj is actually + * not referenced anymore by anybody before we proceed with + * unloading. + */ + wait_for_completion(&data->kobj_unregister); + + if (cpufreq_driver->target) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); + + if (cpufreq_driver->exit) + cpufreq_driver->exit(data); + + kfree(data); + + return 0; +} + +/** + * cpufreq_resume - restore the CPU clock frequency after resume + * + * Restore the CPU clock frequency so that our idea of the current + * frequency reflects the actual hardware. + */ +static int cpufreq_resume(struct sys_device * sysdev) +{ + int cpu = sysdev->id; + unsigned int ret = 0; + struct cpufreq_policy *cpu_policy; + + if (!cpu_online(cpu)) + return 0; + + /* we may be lax here as interrupts are off. Nonetheless + * we need to grab the correct cpu policy, as to check + * whether we really run on this CPU. + */ + + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) + return -EINVAL; + + if (cpufreq_driver->setpolicy) + ret = cpufreq_driver->setpolicy(cpu_policy); + else + /* CPUFREQ_RELATION_H or CPUFREQ_RELATION_L have the same effect here, as cpu_policy->cur is known + * to be a valid and exact target frequency + */ + ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H); + + cpufreq_cpu_put(cpu_policy); + + return ret; +} + +static struct sysdev_driver cpufreq_sysdev_driver = { + .add = cpufreq_add_dev, + .remove = cpufreq_remove_dev, + .resume = cpufreq_resume, +}; + + +/********************************************************************* + * NOTIFIER LISTS INTERFACE * + *********************************************************************/ + +/** + * cpufreq_register_notifier - register a driver with cpufreq + * @nb: notifier function to register + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Add a driver to one of two lists: either a list of drivers that + * are notified about clock rate changes (once before and once after + * the transition), or a list of drivers that are notified about + * changes in cpufreq policy. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_register. + */ +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down_write(&cpufreq_notifier_rwsem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up_write(&cpufreq_notifier_rwsem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_register_notifier); + + +/** + * cpufreq_unregister_notifier - unregister a driver with cpufreq + * @nb: notifier block to be unregistered + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Remove a driver from the CPU frequency notifier list. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_unregister. + */ +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down_write(&cpufreq_notifier_rwsem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up_write(&cpufreq_notifier_rwsem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_unregister_notifier); + + +/********************************************************************* + * GOVERNORS * + *********************************************************************/ + + +int __cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + return cpufreq_driver->target(policy, target_freq, relation); +} +EXPORT_SYMBOL_GPL(__cpufreq_driver_target); + + +int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int ret; + + policy = cpufreq_cpu_get(policy->cpu); + if (!policy) + return -EINVAL; + + down(&policy->lock); + + ret = __cpufreq_driver_target(policy, target_freq, relation); + + up(&policy->lock); + + cpufreq_cpu_put(policy); + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_driver_target); + + +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) +{ + int ret = 0; + + switch (policy->policy) { + case CPUFREQ_POLICY_POWERSAVE: + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { + ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + } + break; + case CPUFREQ_POLICY_PERFORMANCE: + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { + ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + } + break; + case CPUFREQ_POLICY_GOVERNOR: + ret = -EINVAL; + if (!try_module_get(policy->governor->owner)) + break; + ret = policy->governor->governor(policy, event); + /* we keep one module reference alive for each CPU governed by this CPU */ + if ((event != CPUFREQ_GOV_START) || ret) + module_put(policy->governor->owner); + if ((event == CPUFREQ_GOV_STOP) && !ret) + module_put(policy->governor->owner); + break; + default: + ret = -EINVAL; + } + + return ret; +} + + +int cpufreq_governor(unsigned int cpu, unsigned int event) +{ + int ret = 0; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + + if (!policy) + return -EINVAL; + + down(&policy->lock); + ret = __cpufreq_governor(policy, event); + up(&policy->lock); + + cpufreq_cpu_put(policy); + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_governor); + + +int cpufreq_register_governor(struct cpufreq_governor *governor) +{ + struct cpufreq_governor *t; + + if (!governor) + return -EINVAL; + + if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN)) + return -EBUSY; + if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN)) + return -EBUSY; + + down(&cpufreq_governor_sem); + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { + up(&cpufreq_governor_sem); + return -EBUSY; + } + } + list_add(&governor->governor_list, &cpufreq_governor_list); + + up(&cpufreq_governor_sem); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_register_governor); + + +void cpufreq_unregister_governor(struct cpufreq_governor *governor) +{ + if (!governor) + return; + + down(&cpufreq_governor_sem); + list_del(&governor->governor_list); + up(&cpufreq_governor_sem); + return; +} +EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); + + + +/********************************************************************* + * POLICY INTERFACE * + *********************************************************************/ + +/** + * cpufreq_get_policy - get the current cpufreq_policy + * @policy: struct cpufreq_policy into which the current cpufreq_policy is written + * + * Reads the current cpufreq policy. + */ +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) +{ + struct cpufreq_policy *cpu_policy; + if (!policy) + return -EINVAL; + + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) + return -EINVAL; + + down(&cpu_policy->lock); + memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); + up(&cpu_policy->lock); + + cpufreq_cpu_put(cpu_policy); + + return 0; +} +EXPORT_SYMBOL(cpufreq_get_policy); + + +/** + * cpufreq_set_policy - set a new CPUFreq policy + * @policy: policy to be set. + * + * Sets a new CPU frequency and voltage scaling policy. + */ +int cpufreq_set_policy(struct cpufreq_policy *policy) +{ + int ret = 0; + struct cpufreq_policy *data; + + if (!policy) + return -EINVAL; + + data = cpufreq_cpu_get(policy->cpu); + if (!data) + return -EINVAL; + + /* lock this CPU */ + down(&data->lock); + + memcpy(&policy->cpuinfo, + &data->cpuinfo, + sizeof(struct cpufreq_cpuinfo)); + + /* verify the cpu speed can be set within this limit */ + ret = cpufreq_driver->verify(policy); + if (ret) + goto error_out; + + down_read(&cpufreq_notifier_rwsem); + + /* adjust if necessary - all reasons */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, + policy); + + /* adjust if necessary - hardware incompatibility*/ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, + policy); + + /* verify the cpu speed can be set within this limit, + which might be different to the first one */ + ret = cpufreq_driver->verify(policy); + if (ret) { + up_read(&cpufreq_notifier_rwsem); + goto error_out; + } + + /* notification of the new policy */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, + policy); + + up_read(&cpufreq_notifier_rwsem); + + data->min = policy->min; + data->max = policy->max; + + if (cpufreq_driver->setpolicy) { + data->policy = policy->policy; + ret = cpufreq_driver->setpolicy(policy); + } else { + if ((policy->policy != data->policy) || + ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) { + /* save old, working values */ + unsigned int old_pol = data->policy; + struct cpufreq_governor *old_gov = data->governor; + + /* end old governor */ + __cpufreq_governor(data, CPUFREQ_GOV_STOP); + + /* start new governor */ + data->policy = policy->policy; + data->governor = policy->governor; + if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { + /* new governor failed, so re-start old one */ + data->policy = old_pol; + data->governor = old_gov; + __cpufreq_governor(data, CPUFREQ_GOV_START); + } + /* might be a policy change, too, so fall through */ + } + __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); + } + + error_out: + up(&data->lock); + cpufreq_cpu_put(data); + + return ret; +} +EXPORT_SYMBOL(cpufreq_set_policy); + + + +/********************************************************************* + * EXTERNALLY AFFECTING FREQUENCY CHANGES * + *********************************************************************/ + +/** + * adjust_jiffies - adjust the system "loops_per_jiffy" + * + * This function alters the system "loops_per_jiffy" for the clock + * speed change. Note that loops_per_jiffy cannot be updated on SMP + * systems as each CPU might be scaled differently. So, use the arch + * per-CPU loops_per_jiffy value wherever possible. + */ +#ifndef CONFIG_SMP +static unsigned long l_p_j_ref; +static unsigned int l_p_j_ref_freq; + +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +{ + if (!l_p_j_ref_freq) { + l_p_j_ref = loops_per_jiffy; + l_p_j_ref_freq = ci->old; + } + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new)) + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); +} +#else +#define adjust_jiffies(x...) do {} while (0) +#endif + + +/** + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition + * + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called + * twice on all CPU frequency changes that have external effects. + */ +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) +{ + if (irqs_disabled()) + return; /* Only valid if we're in the resume process where + * everyone knows what CPU frequency we are at */ + + down_read(&cpufreq_notifier_rwsem); + switch (state) { + case CPUFREQ_PRECHANGE: + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); + adjust_jiffies(CPUFREQ_PRECHANGE, freqs); + break; + case CPUFREQ_POSTCHANGE: + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); + cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; + break; + } + up_read(&cpufreq_notifier_rwsem); +} +EXPORT_SYMBOL_GPL(cpufreq_notify_transition); + + + +/********************************************************************* + * REGISTER / UNREGISTER CPUFREQ DRIVER * + *********************************************************************/ + +/** + * cpufreq_register_driver - register a CPU Frequency driver + * @driver_data: A struct cpufreq_driver containing the values# + * submitted by the CPU Frequency driver. + * + * Registers a CPU Frequency driver to this core code. This code + * returns zero on success, -EBUSY when another driver got here first + * (and isn't unregistered in the meantime). + * + */ +int cpufreq_register_driver(struct cpufreq_driver *driver_data) +{ + unsigned long flags; + + if (!driver_data || !driver_data->verify || !driver_data->init || + ((!driver_data->setpolicy) && (!driver_data->target))) + return -EINVAL; + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + if (cpufreq_driver) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + return -EBUSY; + } + cpufreq_driver = driver_data; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + return sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver); +} +EXPORT_SYMBOL_GPL(cpufreq_register_driver); + + +/** + * cpufreq_unregister_driver - unregister the current CPUFreq driver + * + * Unregister the current CPUFreq driver. Only call this if you have + * the right to do so, i.e. if you have succeeded in initialising before! + * Returns zero if successful, and -EINVAL if the cpufreq_driver is + * currently not initialised. + */ +int cpufreq_unregister_driver(struct cpufreq_driver *driver) +{ + unsigned long flags; + + if (!cpufreq_driver || (driver != cpufreq_driver)) + return -EINVAL; + + sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_driver = NULL; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); diff --git a/kernel/Makefile b/kernel/Makefile index 9bf11ae7195b..638a2f6c341c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ -obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_IKCONFIG) += configs.o diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c deleted file mode 100644 index 7f80c321c785..000000000000 --- a/kernel/cpufreq.c +++ /dev/null @@ -1,963 +0,0 @@ -/* - * linux/kernel/cpufreq.c - * - * Copyright (C) 2001 Russell King - * (C) 2002 - 2003 Dominik Brodowski - * - * $Id: cpufreq.c,v 1.59 2003/01/20 17:31:48 db Exp $ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * The "cpufreq driver" - the arch- or hardware-dependend low - * level driver of CPUFreq support, and its spinlock. This lock - * also protects the cpufreq_cpu_data array. - */ -static struct cpufreq_driver *cpufreq_driver; -static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; -static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; - -/* internal prototype */ -static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); - - -/** - * Two notifier lists: the "policy" list is involved in the - * validation process for a new CPU frequency policy; the - * "transition" list for kernel code that needs to handle - * changes to devices when the CPU clock speed changes. - * The mutex locks both lists. - */ -static struct notifier_block *cpufreq_policy_notifier_list; -static struct notifier_block *cpufreq_transition_notifier_list; -static DECLARE_RWSEM (cpufreq_notifier_rwsem); - - -static LIST_HEAD(cpufreq_governor_list); -static DECLARE_MUTEX (cpufreq_governor_sem); - -static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) -{ - struct cpufreq_policy *data; - unsigned long flags; - - if (cpu >= NR_CPUS) - goto err_out; - - /* get the cpufreq driver */ - spin_lock_irqsave(&cpufreq_driver_lock, flags); - - if (!cpufreq_driver) - goto err_out_unlock; - - if (!try_module_get(cpufreq_driver->owner)) - goto err_out_unlock; - - - /* get the CPU */ - data = cpufreq_cpu_data[cpu]; - - if (!data) - goto err_out_put_module; - - if (!kobject_get(&data->kobj)) - goto err_out_put_module; - - - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - return data; - - err_out_put_module: - module_put(cpufreq_driver->owner); - err_out_unlock: - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - err_out: - return NULL; -} - -static void cpufreq_cpu_put(struct cpufreq_policy *data) -{ - kobject_put(&data->kobj); - module_put(cpufreq_driver->owner); -} - -/********************************************************************* - * SYSFS INTERFACE * - *********************************************************************/ - -/** - * cpufreq_parse_governor - parse a governor string - */ -int cpufreq_parse_governor (char *str_governor, unsigned int *policy, - struct cpufreq_governor **governor) -{ - if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_PERFORMANCE; - return 0; - } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_POWERSAVE; - return 0; - } else { - struct cpufreq_governor *t; - down(&cpufreq_governor_sem); - if (!cpufreq_driver || !cpufreq_driver->target) - goto out; - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { - *governor = t; - *policy = CPUFREQ_POLICY_GOVERNOR; - up(&cpufreq_governor_sem); - return 0; - } - } - out: - up(&cpufreq_governor_sem); - } - return -EINVAL; -} -EXPORT_SYMBOL_GPL(cpufreq_parse_governor); - - -/* drivers/base/cpu.c */ -extern struct sysdev_class cpu_sysdev_class; - - -/** - * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information - * - * Write out information from cpufreq_driver->policy[cpu]; object must be - * "unsigned int". - */ - -#define show_one(file_name, object) \ -static ssize_t show_##file_name \ -(struct cpufreq_policy * policy, char *buf) \ -{ \ - return sprintf (buf, "%u\n", policy->object); \ -} - -show_one(cpuinfo_min_freq, cpuinfo.min_freq); -show_one(cpuinfo_max_freq, cpuinfo.max_freq); -show_one(scaling_min_freq, min); -show_one(scaling_max_freq, max); - -/** - * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access - */ -#define store_one(file_name, object) \ -static ssize_t store_##file_name \ -(struct cpufreq_policy * policy, const char *buf, size_t count) \ -{ \ - unsigned int ret = -EINVAL; \ - struct cpufreq_policy new_policy; \ - \ - ret = cpufreq_get_policy(&new_policy, policy->cpu); \ - if (ret) \ - return -EINVAL; \ - \ - ret = sscanf (buf, "%u", &new_policy.object); \ - if (ret != 1) \ - return -EINVAL; \ - \ - ret = cpufreq_set_policy(&new_policy); \ - \ - return ret ? ret : count; \ -} - -store_one(scaling_min_freq,min); -store_one(scaling_max_freq,max); - -/** - * show_scaling_governor - show the current policy for the specified CPU - */ -static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) -{ - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - return sprintf(buf, "powersave\n"); - case CPUFREQ_POLICY_PERFORMANCE: - return sprintf(buf, "performance\n"); - case CPUFREQ_POLICY_GOVERNOR: - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); - default: - return -EINVAL; - } -} - - -/** - * store_scaling_governor - store policy for the specified CPU - */ -static ssize_t store_scaling_governor (struct cpufreq_policy * policy, - const char *buf, size_t count) -{ - unsigned int ret = -EINVAL; - char str_governor[16]; - struct cpufreq_policy new_policy; - - ret = cpufreq_get_policy(&new_policy, policy->cpu); - if (ret) - return ret; - - ret = sscanf (buf, "%15s", str_governor); - if (ret != 1) - return -EINVAL; - - if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor)) - return -EINVAL; - - ret = cpufreq_set_policy(&new_policy); - - return ret ? ret : count; -} - -/** - * show_scaling_driver - show the cpufreq driver currently loaded - */ -static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) -{ - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); -} - -/** - * show_scaling_available_governors - show the available CPUfreq governors - */ -static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, - char *buf) -{ - ssize_t i = 0; - struct cpufreq_governor *t; - - i += sprintf(buf, "performance powersave"); - - if (!cpufreq_driver->target) - goto out; - - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) - goto out; - i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name); - } - out: - i += sprintf(&buf[i], "\n"); - return i; -} - - -#define define_one_ro(_name) \ -struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = show_##_name, \ -} - -#define define_one_rw(_name) \ -struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0644 }, \ - .show = show_##_name, \ - .store = store_##_name, \ -} - -define_one_ro(cpuinfo_min_freq); -define_one_ro(cpuinfo_max_freq); -define_one_ro(scaling_available_governors); -define_one_ro(scaling_driver); -define_one_rw(scaling_min_freq); -define_one_rw(scaling_max_freq); -define_one_rw(scaling_governor); - -static struct attribute * default_attrs[] = { - &cpuinfo_min_freq.attr, - &cpuinfo_max_freq.attr, - &scaling_min_freq.attr, - &scaling_max_freq.attr, - &scaling_governor.attr, - &scaling_driver.attr, - &scaling_available_governors.attr, - NULL -}; - -#define to_policy(k) container_of(k,struct cpufreq_policy,kobj) -#define to_attr(a) container_of(a,struct freq_attr,attr) - -static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) -{ - struct cpufreq_policy * policy = to_policy(kobj); - struct freq_attr * fattr = to_attr(attr); - ssize_t ret; - policy = cpufreq_cpu_get(policy->cpu); - if (!policy) - return -EINVAL; - ret = fattr->show ? fattr->show(policy,buf) : 0; - cpufreq_cpu_put(policy); - return ret; -} - -static ssize_t store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) -{ - struct cpufreq_policy * policy = to_policy(kobj); - struct freq_attr * fattr = to_attr(attr); - ssize_t ret; - policy = cpufreq_cpu_get(policy->cpu); - if (!policy) - return -EINVAL; - ret = fattr->store ? fattr->store(policy,buf,count) : 0; - cpufreq_cpu_put(policy); - return ret; -} - -static void cpufreq_sysfs_release(struct kobject * kobj) -{ - struct cpufreq_policy * policy = to_policy(kobj); - complete(&policy->kobj_unregister); -} - -static struct sysfs_ops sysfs_ops = { - .show = show, - .store = store, -}; - -static struct kobj_type ktype_cpufreq = { - .sysfs_ops = &sysfs_ops, - .default_attrs = default_attrs, - .release = cpufreq_sysfs_release, -}; - - -/** - * cpufreq_add_dev - add a CPU device - * - * Adds the cpufreq interface for a CPU device. - */ -static int cpufreq_add_dev (struct sys_device * sys_dev) -{ - unsigned int cpu = sys_dev->id; - int ret = 0; - struct cpufreq_policy new_policy; - struct cpufreq_policy *policy; - struct freq_attr **drv_attr; - unsigned long flags; - - if (!try_module_get(cpufreq_driver->owner)) - return -EINVAL; - - policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); - if (!policy) - return -ENOMEM; - memset(policy, 0, sizeof(struct cpufreq_policy)); - - policy->cpu = cpu; - init_MUTEX_LOCKED(&policy->lock); - init_completion(&policy->kobj_unregister); - - /* call driver. From then on the cpufreq must be able - * to accept all calls to ->verify and ->setpolicy for this CPU - */ - ret = cpufreq_driver->init(policy); - if (ret) - goto err_out; - - memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); - - /* prepare interface data */ - policy->kobj.parent = &sys_dev->kobj; - policy->kobj.ktype = &ktype_cpufreq; - strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); - - ret = kobject_register(&policy->kobj); - if (ret) - goto err_out; - - /* set up files for this cpu device */ - drv_attr = cpufreq_driver->attr; - while ((drv_attr) && (*drv_attr)) { - sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); - drv_attr++; - } - - spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpufreq_cpu_data[cpu] = policy; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - up(&policy->lock); - - /* set default policy */ - ret = cpufreq_set_policy(&new_policy); - if (ret) - goto err_out_unregister; - - module_put(cpufreq_driver->owner); - return 0; - - - err_out_unregister: - spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpufreq_cpu_data[cpu] = NULL; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - kobject_unregister(&policy->kobj); - wait_for_completion(&policy->kobj_unregister); - - err_out: - kfree(policy); - module_put(cpufreq_driver->owner); - return ret; -} - - -/** - * cpufreq_remove_dev - remove a CPU device - * - * Removes the cpufreq interface for a CPU device. - */ -static int cpufreq_remove_dev (struct sys_device * sys_dev) -{ - unsigned int cpu = sys_dev->id; - unsigned long flags; - struct cpufreq_policy *data; - - spin_lock_irqsave(&cpufreq_driver_lock, flags); - data = cpufreq_cpu_data[cpu]; - - if (!data) { - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - return -EINVAL; - } - cpufreq_cpu_data[cpu] = NULL; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - if (!kobject_get(&data->kobj)) - return -EFAULT; - - kobject_unregister(&data->kobj); - - kobject_put(&data->kobj); - - /* we need to make sure that the underlying kobj is actually - * not referenced anymore by anybody before we proceed with - * unloading. - */ - wait_for_completion(&data->kobj_unregister); - - if (cpufreq_driver->target) - __cpufreq_governor(data, CPUFREQ_GOV_STOP); - - if (cpufreq_driver->exit) - cpufreq_driver->exit(data); - - kfree(data); - - return 0; -} - -/** - * cpufreq_resume - restore the CPU clock frequency after resume - * - * Restore the CPU clock frequency so that our idea of the current - * frequency reflects the actual hardware. - */ -static int cpufreq_resume(struct sys_device * sysdev) -{ - int cpu = sysdev->id; - unsigned int ret = 0; - struct cpufreq_policy *cpu_policy; - - if (!cpu_online(cpu)) - return 0; - - /* we may be lax here as interrupts are off. Nonetheless - * we need to grab the correct cpu policy, as to check - * whether we really run on this CPU. - */ - - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) - return -EINVAL; - - if (cpufreq_driver->setpolicy) - ret = cpufreq_driver->setpolicy(cpu_policy); - else - /* CPUFREQ_RELATION_H or CPUFREQ_RELATION_L have the same effect here, as cpu_policy->cur is known - * to be a valid and exact target frequency - */ - ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H); - - cpufreq_cpu_put(cpu_policy); - - return ret; -} - -static struct sysdev_driver cpufreq_sysdev_driver = { - .add = cpufreq_add_dev, - .remove = cpufreq_remove_dev, - .resume = cpufreq_resume, -}; - - -/********************************************************************* - * NOTIFIER LISTS INTERFACE * - *********************************************************************/ - -/** - * cpufreq_register_notifier - register a driver with cpufreq - * @nb: notifier function to register - * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER - * - * Add a driver to one of two lists: either a list of drivers that - * are notified about clock rate changes (once before and once after - * the transition), or a list of drivers that are notified about - * changes in cpufreq policy. - * - * This function may sleep, and has the same return conditions as - * notifier_chain_register. - */ -int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) -{ - int ret; - - down_write(&cpufreq_notifier_rwsem); - switch (list) { - case CPUFREQ_TRANSITION_NOTIFIER: - ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); - break; - case CPUFREQ_POLICY_NOTIFIER: - ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); - break; - default: - ret = -EINVAL; - } - up_write(&cpufreq_notifier_rwsem); - - return ret; -} -EXPORT_SYMBOL(cpufreq_register_notifier); - - -/** - * cpufreq_unregister_notifier - unregister a driver with cpufreq - * @nb: notifier block to be unregistered - * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER - * - * Remove a driver from the CPU frequency notifier list. - * - * This function may sleep, and has the same return conditions as - * notifier_chain_unregister. - */ -int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) -{ - int ret; - - down_write(&cpufreq_notifier_rwsem); - switch (list) { - case CPUFREQ_TRANSITION_NOTIFIER: - ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); - break; - case CPUFREQ_POLICY_NOTIFIER: - ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); - break; - default: - ret = -EINVAL; - } - up_write(&cpufreq_notifier_rwsem); - - return ret; -} -EXPORT_SYMBOL(cpufreq_unregister_notifier); - - -/********************************************************************* - * GOVERNORS * - *********************************************************************/ - - -int __cpufreq_driver_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - return cpufreq_driver->target(policy, target_freq, relation); -} -EXPORT_SYMBOL_GPL(__cpufreq_driver_target); - - -int cpufreq_driver_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int ret; - - policy = cpufreq_cpu_get(policy->cpu); - if (!policy) - return -EINVAL; - - down(&policy->lock); - - ret = __cpufreq_driver_target(policy, target_freq, relation); - - up(&policy->lock); - - cpufreq_cpu_put(policy); - - return ret; -} -EXPORT_SYMBOL_GPL(cpufreq_driver_target); - - -static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) -{ - int ret = 0; - - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); - } - break; - case CPUFREQ_POLICY_PERFORMANCE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - } - break; - case CPUFREQ_POLICY_GOVERNOR: - ret = -EINVAL; - if (!try_module_get(policy->governor->owner)) - break; - ret = policy->governor->governor(policy, event); - /* we keep one module reference alive for each CPU governed by this CPU */ - if ((event != CPUFREQ_GOV_START) || ret) - module_put(policy->governor->owner); - if ((event == CPUFREQ_GOV_STOP) && !ret) - module_put(policy->governor->owner); - break; - default: - ret = -EINVAL; - } - - return ret; -} - - -int cpufreq_governor(unsigned int cpu, unsigned int event) -{ - int ret = 0; - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - - if (!policy) - return -EINVAL; - - down(&policy->lock); - ret = __cpufreq_governor(policy, event); - up(&policy->lock); - - cpufreq_cpu_put(policy); - - return ret; -} -EXPORT_SYMBOL_GPL(cpufreq_governor); - - -int cpufreq_register_governor(struct cpufreq_governor *governor) -{ - struct cpufreq_governor *t; - - if (!governor) - return -EINVAL; - - if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN)) - return -EBUSY; - if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN)) - return -EBUSY; - - down(&cpufreq_governor_sem); - - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { - up(&cpufreq_governor_sem); - return -EBUSY; - } - } - list_add(&governor->governor_list, &cpufreq_governor_list); - - up(&cpufreq_governor_sem); - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_register_governor); - - -void cpufreq_unregister_governor(struct cpufreq_governor *governor) -{ - if (!governor) - return; - - down(&cpufreq_governor_sem); - list_del(&governor->governor_list); - up(&cpufreq_governor_sem); - return; -} -EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); - - - -/********************************************************************* - * POLICY INTERFACE * - *********************************************************************/ - -/** - * cpufreq_get_policy - get the current cpufreq_policy - * @policy: struct cpufreq_policy into which the current cpufreq_policy is written - * - * Reads the current cpufreq policy. - */ -int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) -{ - struct cpufreq_policy *cpu_policy; - if (!policy) - return -EINVAL; - - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) - return -EINVAL; - - down(&cpu_policy->lock); - memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); - up(&cpu_policy->lock); - - cpufreq_cpu_put(cpu_policy); - - return 0; -} -EXPORT_SYMBOL(cpufreq_get_policy); - - -/** - * cpufreq_set_policy - set a new CPUFreq policy - * @policy: policy to be set. - * - * Sets a new CPU frequency and voltage scaling policy. - */ -int cpufreq_set_policy(struct cpufreq_policy *policy) -{ - int ret = 0; - struct cpufreq_policy *data; - - if (!policy) - return -EINVAL; - - data = cpufreq_cpu_get(policy->cpu); - if (!data) - return -EINVAL; - - /* lock this CPU */ - down(&data->lock); - - memcpy(&policy->cpuinfo, - &data->cpuinfo, - sizeof(struct cpufreq_cpuinfo)); - - /* verify the cpu speed can be set within this limit */ - ret = cpufreq_driver->verify(policy); - if (ret) - goto error_out; - - down_read(&cpufreq_notifier_rwsem); - - /* adjust if necessary - all reasons */ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, - policy); - - /* adjust if necessary - hardware incompatibility*/ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, - policy); - - /* verify the cpu speed can be set within this limit, - which might be different to the first one */ - ret = cpufreq_driver->verify(policy); - if (ret) { - up_read(&cpufreq_notifier_rwsem); - goto error_out; - } - - /* notification of the new policy */ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, - policy); - - up_read(&cpufreq_notifier_rwsem); - - data->min = policy->min; - data->max = policy->max; - - if (cpufreq_driver->setpolicy) { - data->policy = policy->policy; - ret = cpufreq_driver->setpolicy(policy); - } else { - if ((policy->policy != data->policy) || - ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) { - /* save old, working values */ - unsigned int old_pol = data->policy; - struct cpufreq_governor *old_gov = data->governor; - - /* end old governor */ - __cpufreq_governor(data, CPUFREQ_GOV_STOP); - - /* start new governor */ - data->policy = policy->policy; - data->governor = policy->governor; - if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { - /* new governor failed, so re-start old one */ - data->policy = old_pol; - data->governor = old_gov; - __cpufreq_governor(data, CPUFREQ_GOV_START); - } - /* might be a policy change, too, so fall through */ - } - __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); - } - - error_out: - up(&data->lock); - cpufreq_cpu_put(data); - - return ret; -} -EXPORT_SYMBOL(cpufreq_set_policy); - - - -/********************************************************************* - * EXTERNALLY AFFECTING FREQUENCY CHANGES * - *********************************************************************/ - -/** - * adjust_jiffies - adjust the system "loops_per_jiffy" - * - * This function alters the system "loops_per_jiffy" for the clock - * speed change. Note that loops_per_jiffy cannot be updated on SMP - * systems as each CPU might be scaled differently. So, use the arch - * per-CPU loops_per_jiffy value wherever possible. - */ -#ifndef CONFIG_SMP -static unsigned long l_p_j_ref; -static unsigned int l_p_j_ref_freq; - -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) -{ - if (!l_p_j_ref_freq) { - l_p_j_ref = loops_per_jiffy; - l_p_j_ref_freq = ci->old; - } - if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || - (val == CPUFREQ_POSTCHANGE && ci->old > ci->new)) - loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); -} -#else -#define adjust_jiffies(x...) do {} while (0) -#endif - - -/** - * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition - * - * This function calls the transition notifiers and the "adjust_jiffies" function. It is called - * twice on all CPU frequency changes that have external effects. - */ -void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) -{ - if (irqs_disabled()) - return; /* Only valid if we're in the resume process where - * everyone knows what CPU frequency we are at */ - - down_read(&cpufreq_notifier_rwsem); - switch (state) { - case CPUFREQ_PRECHANGE: - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); - adjust_jiffies(CPUFREQ_PRECHANGE, freqs); - break; - case CPUFREQ_POSTCHANGE: - adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); - cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; - break; - } - up_read(&cpufreq_notifier_rwsem); -} -EXPORT_SYMBOL_GPL(cpufreq_notify_transition); - - - -/********************************************************************* - * REGISTER / UNREGISTER CPUFREQ DRIVER * - *********************************************************************/ - -/** - * cpufreq_register_driver - register a CPU Frequency driver - * @driver_data: A struct cpufreq_driver containing the values# - * submitted by the CPU Frequency driver. - * - * Registers a CPU Frequency driver to this core code. This code - * returns zero on success, -EBUSY when another driver got here first - * (and isn't unregistered in the meantime). - * - */ -int cpufreq_register_driver(struct cpufreq_driver *driver_data) -{ - unsigned long flags; - - if (!driver_data || !driver_data->verify || !driver_data->init || - ((!driver_data->setpolicy) && (!driver_data->target))) - return -EINVAL; - - spin_lock_irqsave(&cpufreq_driver_lock, flags); - if (cpufreq_driver) { - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - return -EBUSY; - } - cpufreq_driver = driver_data; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - return sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver); -} -EXPORT_SYMBOL_GPL(cpufreq_register_driver); - - -/** - * cpufreq_unregister_driver - unregister the current CPUFreq driver - * - * Unregister the current CPUFreq driver. Only call this if you have - * the right to do so, i.e. if you have succeeded in initialising before! - * Returns zero if successful, and -EINVAL if the cpufreq_driver is - * currently not initialised. - */ -int cpufreq_unregister_driver(struct cpufreq_driver *driver) -{ - unsigned long flags; - - if (!cpufreq_driver || (driver != cpufreq_driver)) - return -EINVAL; - - sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); - - spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpufreq_driver = NULL; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); -- cgit v1.2.3 From f2f18872dda81a9f34483a288ae8e1351e3c1664 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 01:31:13 +0100 Subject: [CPUFREQ] fix up two typos. cpuferq hakcers cnat spel. --- Documentation/cpu-freq/cpu-drivers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index be5c94d0f753..bf4c682bc696 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -119,7 +119,7 @@ section 2 for details on frequency table helpers. You need to make sure that at least one valid frequency (or operating range) is within policy->min and policy->max. If necessary, increase -policy->max fist, and only if this is no solution, decreas policy->min. +policy->max first, and only if this is no solution, decrease policy->min. 1.4 target or setpolicy? -- cgit v1.2.3 From 2e4dc88bcfa8d275b56fc24520b01984d4e8534b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 02:14:53 +0100 Subject: [CPUFREQ] Move drivers/cpufreq/userspace.c to drivers/cpufreq/cpufreq_userspace.c Module names of 'userspace' aren't very informative. --- drivers/cpufreq/Makefile | 2 +- drivers/cpufreq/cpufreq_userspace.c | 591 ++++++++++++++++++++++++++++++++++++ drivers/cpufreq/userspace.c | 591 ------------------------------------ 3 files changed, 592 insertions(+), 592 deletions(-) create mode 100644 drivers/cpufreq/cpufreq_userspace.c delete mode 100644 drivers/cpufreq/userspace.c diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 98d532579bf4..e65dca095a53 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o # CPUfreq governors -obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c new file mode 100644 index 000000000000..7df32a97c50a --- /dev/null +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -0,0 +1,591 @@ +/* + * drivers/cpufreq/userspace.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2003 Dominik Brodowski + * + * $Id:$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \ + .ctl_name = CPU_NR_FREQ_MAX, \ + .data = &cpu_max_freq[cpunr], \ + .procname = "speed-max", \ + .maxlen = sizeof(cpu_max_freq[cpunr]),\ + .mode = 0444, \ + .proc_handler = proc_dointvec, } + +#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \ + .ctl_name = CPU_NR_FREQ_MIN, \ + .data = &cpu_min_freq[cpunr], \ + .procname = "speed-min", \ + .maxlen = sizeof(cpu_min_freq[cpunr]),\ + .mode = 0444, \ + .proc_handler = proc_dointvec, } + +#define CTL_CPU_VARS_SPEED(cpunr) { \ + .ctl_name = CPU_NR_FREQ, \ + .procname = "speed", \ + .mode = 0644, \ + .proc_handler = cpufreq_procctl, \ + .strategy = cpufreq_sysctl, \ + .extra1 = (void*) (cpunr), } + +#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\ + CTL_CPU_VARS_SPEED_MAX(cpunr), \ + CTL_CPU_VARS_SPEED_MIN(cpunr), \ + CTL_CPU_VARS_SPEED(cpunr), \ + { .ctl_name = 0, }, } + +/* the ctl_table entry for each CPU */ +#define CPU_ENUM(s) { \ + .ctl_name = (CPU_NR + s), \ + .procname = #s, \ + .mode = 0555, \ + .child = ctl_cpu_vars_##s } + +/** + * A few values needed by the userspace governor + */ +static unsigned int cpu_max_freq[NR_CPUS]; +static unsigned int cpu_min_freq[NR_CPUS]; +static unsigned int cpu_cur_freq[NR_CPUS]; +static unsigned int cpu_is_managed[NR_CPUS]; +static struct cpufreq_policy current_policy[NR_CPUS]; + +static DECLARE_MUTEX (userspace_sem); + + +/* keep track of frequency transitions */ +static int +userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + + cpu_cur_freq[freq->cpu] = freq->new; + + return 0; +} + +static struct notifier_block userspace_cpufreq_notifier_block = { + .notifier_call = userspace_cpufreq_notifier +}; + + +/** + * cpufreq_set - set the CPU frequency + * @freq: target frequency in kHz + * @cpu: CPU for which the frequency is to be set + * + * Sets the CPU frequency to freq. + */ +int cpufreq_set(unsigned int freq, unsigned int cpu) +{ + int ret = -EINVAL; + + down(&userspace_sem); + if (!cpu_is_managed[cpu]) + goto err; + + if (freq < cpu_min_freq[cpu]) + freq = cpu_min_freq[cpu]; + if (freq > cpu_max_freq[cpu]) + freq = cpu_max_freq[cpu]; + + ret = cpufreq_driver_target(¤t_policy[cpu], freq, + CPUFREQ_RELATION_L); + + err: + up(&userspace_sem); + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_set); + + +/** + * cpufreq_setmax - set the CPU to the maximum frequency + * @cpu - affected cpu; + * + * Sets the CPU frequency to the maximum frequency supported by + * this CPU. + */ +int cpufreq_setmax(unsigned int cpu) +{ + if (!cpu_is_managed[cpu] || !cpu_online(cpu)) + return -EINVAL; + return cpufreq_set(cpu_max_freq[cpu], cpu); +} +EXPORT_SYMBOL_GPL(cpufreq_setmax); + + +/** + * cpufreq_get - get the current CPU frequency (in kHz) + * @cpu: CPU number + * + * Get the CPU current (static) CPU frequency + */ +unsigned int cpufreq_get(unsigned int cpu) +{ + return cpu_cur_freq[cpu]; +} +EXPORT_SYMBOL(cpufreq_get); + + +#ifdef CONFIG_CPU_FREQ_24_API + + +/*********************** cpufreq_sysctl interface ********************/ +static int +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, + void __user *buffer, size_t *lenp) +{ + char buf[16], *p; + int cpu = (int) ctl->extra1; + int len, left = *lenp; + + if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) { + *lenp = 0; + return 0; + } + + if (write) { + unsigned int freq; + + len = left; + if (left > sizeof(buf)) + left = sizeof(buf); + if (copy_from_user(buf, buffer, left)) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + + freq = simple_strtoul(buf, &p, 0); + cpufreq_set(freq, cpu); + } else { + len = sprintf(buf, "%d\n", cpufreq_get(cpu)); + if (len > left) + len = left; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + } + + *lenp = len; + filp->f_pos += len; + return 0; +} + +static int +cpufreq_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + int cpu = (int) table->extra1; + + if (!cpu_online(cpu)) + return -EINVAL; + + if (oldval && oldlenp) { + size_t oldlen; + + if (get_user(oldlen, oldlenp)) + return -EFAULT; + + if (oldlen != sizeof(unsigned int)) + return -EINVAL; + + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) || + put_user(sizeof(unsigned int), oldlenp)) + return -EFAULT; + } + if (newval && newlen) { + unsigned int freq; + + if (newlen != sizeof(unsigned int)) + return -EINVAL; + + if (get_user(freq, (unsigned int *)newval)) + return -EFAULT; + + cpufreq_set(freq, cpu); + } + return 1; +} + +/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */ +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ + CTL_TABLE_CPU_VARS(0); +#if NR_CPUS > 1 + CTL_TABLE_CPU_VARS(1); +#endif +#if NR_CPUS > 2 + CTL_TABLE_CPU_VARS(2); +#endif +#if NR_CPUS > 3 + CTL_TABLE_CPU_VARS(3); +#endif +#if NR_CPUS > 4 + CTL_TABLE_CPU_VARS(4); +#endif +#if NR_CPUS > 5 + CTL_TABLE_CPU_VARS(5); +#endif +#if NR_CPUS > 6 + CTL_TABLE_CPU_VARS(6); +#endif +#if NR_CPUS > 7 + CTL_TABLE_CPU_VARS(7); +#endif +#if NR_CPUS > 8 + CTL_TABLE_CPU_VARS(8); +#endif +#if NR_CPUS > 9 + CTL_TABLE_CPU_VARS(9); +#endif +#if NR_CPUS > 10 + CTL_TABLE_CPU_VARS(10); +#endif +#if NR_CPUS > 11 + CTL_TABLE_CPU_VARS(11); +#endif +#if NR_CPUS > 12 + CTL_TABLE_CPU_VARS(12); +#endif +#if NR_CPUS > 13 + CTL_TABLE_CPU_VARS(13); +#endif +#if NR_CPUS > 14 + CTL_TABLE_CPU_VARS(14); +#endif +#if NR_CPUS > 15 + CTL_TABLE_CPU_VARS(15); +#endif +#if NR_CPUS > 16 + CTL_TABLE_CPU_VARS(16); +#endif +#if NR_CPUS > 17 + CTL_TABLE_CPU_VARS(17); +#endif +#if NR_CPUS > 18 + CTL_TABLE_CPU_VARS(18); +#endif +#if NR_CPUS > 19 + CTL_TABLE_CPU_VARS(19); +#endif +#if NR_CPUS > 20 + CTL_TABLE_CPU_VARS(20); +#endif +#if NR_CPUS > 21 + CTL_TABLE_CPU_VARS(21); +#endif +#if NR_CPUS > 22 + CTL_TABLE_CPU_VARS(22); +#endif +#if NR_CPUS > 23 + CTL_TABLE_CPU_VARS(23); +#endif +#if NR_CPUS > 24 + CTL_TABLE_CPU_VARS(24); +#endif +#if NR_CPUS > 25 + CTL_TABLE_CPU_VARS(25); +#endif +#if NR_CPUS > 26 + CTL_TABLE_CPU_VARS(26); +#endif +#if NR_CPUS > 27 + CTL_TABLE_CPU_VARS(27); +#endif +#if NR_CPUS > 28 + CTL_TABLE_CPU_VARS(28); +#endif +#if NR_CPUS > 29 + CTL_TABLE_CPU_VARS(29); +#endif +#if NR_CPUS > 30 + CTL_TABLE_CPU_VARS(30); +#endif +#if NR_CPUS > 31 + CTL_TABLE_CPU_VARS(31); +#endif +#if NR_CPUS > 32 +#error please extend CPU enumeration +#endif + +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ +static ctl_table ctl_cpu_table[NR_CPUS + 1] = { + CPU_ENUM(0), +#if NR_CPUS > 1 + CPU_ENUM(1), +#endif +#if NR_CPUS > 2 + CPU_ENUM(2), +#endif +#if NR_CPUS > 3 + CPU_ENUM(3), +#endif +#if NR_CPUS > 4 + CPU_ENUM(4), +#endif +#if NR_CPUS > 5 + CPU_ENUM(5), +#endif +#if NR_CPUS > 6 + CPU_ENUM(6), +#endif +#if NR_CPUS > 7 + CPU_ENUM(7), +#endif +#if NR_CPUS > 8 + CPU_ENUM(8), +#endif +#if NR_CPUS > 9 + CPU_ENUM(9), +#endif +#if NR_CPUS > 10 + CPU_ENUM(10), +#endif +#if NR_CPUS > 11 + CPU_ENUM(11), +#endif +#if NR_CPUS > 12 + CPU_ENUM(12), +#endif +#if NR_CPUS > 13 + CPU_ENUM(13), +#endif +#if NR_CPUS > 14 + CPU_ENUM(14), +#endif +#if NR_CPUS > 15 + CPU_ENUM(15), +#endif +#if NR_CPUS > 16 + CPU_ENUM(16), +#endif +#if NR_CPUS > 17 + CPU_ENUM(17), +#endif +#if NR_CPUS > 18 + CPU_ENUM(18), +#endif +#if NR_CPUS > 19 + CPU_ENUM(19), +#endif +#if NR_CPUS > 20 + CPU_ENUM(20), +#endif +#if NR_CPUS > 21 + CPU_ENUM(21), +#endif +#if NR_CPUS > 22 + CPU_ENUM(22), +#endif +#if NR_CPUS > 23 + CPU_ENUM(23), +#endif +#if NR_CPUS > 24 + CPU_ENUM(24), +#endif +#if NR_CPUS > 25 + CPU_ENUM(25), +#endif +#if NR_CPUS > 26 + CPU_ENUM(26), +#endif +#if NR_CPUS > 27 + CPU_ENUM(27), +#endif +#if NR_CPUS > 28 + CPU_ENUM(28), +#endif +#if NR_CPUS > 29 + CPU_ENUM(29), +#endif +#if NR_CPUS > 30 + CPU_ENUM(30), +#endif +#if NR_CPUS > 31 + CPU_ENUM(31), +#endif +#if NR_CPUS > 32 +#error please extend CPU enumeration +#endif + { + .ctl_name = 0, + } +}; + +static ctl_table ctl_cpu[2] = { + { + .ctl_name = CTL_CPU, + .procname = "cpu", + .mode = 0555, + .child = ctl_cpu_table, + }, + { + .ctl_name = 0, + } +}; + +struct ctl_table_header *cpufreq_sysctl_table; + +static inline void cpufreq_sysctl_init(void) +{ + cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0); +} + +static inline void cpufreq_sysctl_exit(void) +{ + unregister_sysctl_table(cpufreq_sysctl_table); +} + +#else +#define cpufreq_sysctl_init() do {} while(0) +#define cpufreq_sysctl_exit() do {} while(0) +#endif /* CONFIG_CPU_FREQ_24API */ + + +/************************** sysfs interface ************************/ +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); +} + +static ssize_t +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) +{ + unsigned int freq = 0; + unsigned int ret; + + ret = sscanf (buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + cpufreq_set(freq, policy->cpu); + + return count; +} + +static struct freq_attr freq_attr_scaling_setspeed = { + .attr = { .name = "scaling_setspeed", .mode = 0644 }, + .show = show_speed, + .store = store_speed, +}; + +static int cpufreq_governor_userspace(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) || + !policy->cur) + return -EINVAL; + down(&userspace_sem); + cpu_is_managed[cpu] = 1; + cpu_min_freq[cpu] = policy->min; + cpu_max_freq[cpu] = policy->max; + cpu_cur_freq[cpu] = policy->cur; + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); + memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); + up(&userspace_sem); + break; + case CPUFREQ_GOV_STOP: + down(&userspace_sem); + cpu_is_managed[cpu] = 0; + cpu_min_freq[cpu] = 0; + cpu_max_freq[cpu] = 0; + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); + up(&userspace_sem); + module_put(THIS_MODULE); + break; + case CPUFREQ_GOV_LIMITS: + down(&userspace_sem); + cpu_min_freq[cpu] = policy->min; + cpu_max_freq[cpu] = policy->max; + if (policy->max < cpu_cur_freq[cpu]) + __cpufreq_driver_target(¤t_policy[cpu], policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > cpu_cur_freq[cpu]) + __cpufreq_driver_target(¤t_policy[cpu], policy->min, + CPUFREQ_RELATION_L); + memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); + up(&userspace_sem); + break; + } + return 0; +} + +/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because + * of this, cpu_cur_freq[] needs to be set early. + */ +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100) +extern unsigned int sa11x0_getspeed(void); + +static void cpufreq_sa11x0_compat(void) +{ + cpu_cur_freq[0] = sa11x0_getspeed(); +} +#else +#define cpufreq_sa11x0_compat() do {} while(0) +#endif + + +static struct cpufreq_governor cpufreq_gov_userspace = { + .name = "userspace", + .governor = cpufreq_governor_userspace, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(cpufreq_gov_userspace); + +static int already_init = 0; + +int cpufreq_gov_userspace_init(void) +{ + if (!already_init) { + down(&userspace_sem); + cpufreq_sa11x0_compat(); + cpufreq_sysctl_init(); + cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + already_init = 1; + up(&userspace_sem); + } + return cpufreq_register_governor(&cpufreq_gov_userspace); +} +EXPORT_SYMBOL(cpufreq_gov_userspace_init); + + +static void __exit cpufreq_gov_userspace_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_userspace); + cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + cpufreq_sysctl_exit(); +} + + +MODULE_AUTHOR ("Dominik Brodowski , Russell King "); +MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_gov_userspace_init); +module_exit(cpufreq_gov_userspace_exit); diff --git a/drivers/cpufreq/userspace.c b/drivers/cpufreq/userspace.c deleted file mode 100644 index 7df32a97c50a..000000000000 --- a/drivers/cpufreq/userspace.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * drivers/cpufreq/userspace.c - * - * Copyright (C) 2001 Russell King - * (C) 2002 - 2003 Dominik Brodowski - * - * $Id:$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \ - .ctl_name = CPU_NR_FREQ_MAX, \ - .data = &cpu_max_freq[cpunr], \ - .procname = "speed-max", \ - .maxlen = sizeof(cpu_max_freq[cpunr]),\ - .mode = 0444, \ - .proc_handler = proc_dointvec, } - -#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \ - .ctl_name = CPU_NR_FREQ_MIN, \ - .data = &cpu_min_freq[cpunr], \ - .procname = "speed-min", \ - .maxlen = sizeof(cpu_min_freq[cpunr]),\ - .mode = 0444, \ - .proc_handler = proc_dointvec, } - -#define CTL_CPU_VARS_SPEED(cpunr) { \ - .ctl_name = CPU_NR_FREQ, \ - .procname = "speed", \ - .mode = 0644, \ - .proc_handler = cpufreq_procctl, \ - .strategy = cpufreq_sysctl, \ - .extra1 = (void*) (cpunr), } - -#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\ - CTL_CPU_VARS_SPEED_MAX(cpunr), \ - CTL_CPU_VARS_SPEED_MIN(cpunr), \ - CTL_CPU_VARS_SPEED(cpunr), \ - { .ctl_name = 0, }, } - -/* the ctl_table entry for each CPU */ -#define CPU_ENUM(s) { \ - .ctl_name = (CPU_NR + s), \ - .procname = #s, \ - .mode = 0555, \ - .child = ctl_cpu_vars_##s } - -/** - * A few values needed by the userspace governor - */ -static unsigned int cpu_max_freq[NR_CPUS]; -static unsigned int cpu_min_freq[NR_CPUS]; -static unsigned int cpu_cur_freq[NR_CPUS]; -static unsigned int cpu_is_managed[NR_CPUS]; -static struct cpufreq_policy current_policy[NR_CPUS]; - -static DECLARE_MUTEX (userspace_sem); - - -/* keep track of frequency transitions */ -static int -userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freq = data; - - cpu_cur_freq[freq->cpu] = freq->new; - - return 0; -} - -static struct notifier_block userspace_cpufreq_notifier_block = { - .notifier_call = userspace_cpufreq_notifier -}; - - -/** - * cpufreq_set - set the CPU frequency - * @freq: target frequency in kHz - * @cpu: CPU for which the frequency is to be set - * - * Sets the CPU frequency to freq. - */ -int cpufreq_set(unsigned int freq, unsigned int cpu) -{ - int ret = -EINVAL; - - down(&userspace_sem); - if (!cpu_is_managed[cpu]) - goto err; - - if (freq < cpu_min_freq[cpu]) - freq = cpu_min_freq[cpu]; - if (freq > cpu_max_freq[cpu]) - freq = cpu_max_freq[cpu]; - - ret = cpufreq_driver_target(¤t_policy[cpu], freq, - CPUFREQ_RELATION_L); - - err: - up(&userspace_sem); - return ret; -} -EXPORT_SYMBOL_GPL(cpufreq_set); - - -/** - * cpufreq_setmax - set the CPU to the maximum frequency - * @cpu - affected cpu; - * - * Sets the CPU frequency to the maximum frequency supported by - * this CPU. - */ -int cpufreq_setmax(unsigned int cpu) -{ - if (!cpu_is_managed[cpu] || !cpu_online(cpu)) - return -EINVAL; - return cpufreq_set(cpu_max_freq[cpu], cpu); -} -EXPORT_SYMBOL_GPL(cpufreq_setmax); - - -/** - * cpufreq_get - get the current CPU frequency (in kHz) - * @cpu: CPU number - * - * Get the CPU current (static) CPU frequency - */ -unsigned int cpufreq_get(unsigned int cpu) -{ - return cpu_cur_freq[cpu]; -} -EXPORT_SYMBOL(cpufreq_get); - - -#ifdef CONFIG_CPU_FREQ_24_API - - -/*********************** cpufreq_sysctl interface ********************/ -static int -cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp) -{ - char buf[16], *p; - int cpu = (int) ctl->extra1; - int len, left = *lenp; - - if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) { - *lenp = 0; - return 0; - } - - if (write) { - unsigned int freq; - - len = left; - if (left > sizeof(buf)) - left = sizeof(buf); - if (copy_from_user(buf, buffer, left)) - return -EFAULT; - buf[sizeof(buf) - 1] = '\0'; - - freq = simple_strtoul(buf, &p, 0); - cpufreq_set(freq, cpu); - } else { - len = sprintf(buf, "%d\n", cpufreq_get(cpu)); - if (len > left) - len = left; - if (copy_to_user(buffer, buf, len)) - return -EFAULT; - } - - *lenp = len; - filp->f_pos += len; - return 0; -} - -static int -cpufreq_sysctl(ctl_table *table, int __user *name, int nlen, - void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen, void **context) -{ - int cpu = (int) table->extra1; - - if (!cpu_online(cpu)) - return -EINVAL; - - if (oldval && oldlenp) { - size_t oldlen; - - if (get_user(oldlen, oldlenp)) - return -EFAULT; - - if (oldlen != sizeof(unsigned int)) - return -EINVAL; - - if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) || - put_user(sizeof(unsigned int), oldlenp)) - return -EFAULT; - } - if (newval && newlen) { - unsigned int freq; - - if (newlen != sizeof(unsigned int)) - return -EINVAL; - - if (get_user(freq, (unsigned int *)newval)) - return -EFAULT; - - cpufreq_set(freq, cpu); - } - return 1; -} - -/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */ -/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ - CTL_TABLE_CPU_VARS(0); -#if NR_CPUS > 1 - CTL_TABLE_CPU_VARS(1); -#endif -#if NR_CPUS > 2 - CTL_TABLE_CPU_VARS(2); -#endif -#if NR_CPUS > 3 - CTL_TABLE_CPU_VARS(3); -#endif -#if NR_CPUS > 4 - CTL_TABLE_CPU_VARS(4); -#endif -#if NR_CPUS > 5 - CTL_TABLE_CPU_VARS(5); -#endif -#if NR_CPUS > 6 - CTL_TABLE_CPU_VARS(6); -#endif -#if NR_CPUS > 7 - CTL_TABLE_CPU_VARS(7); -#endif -#if NR_CPUS > 8 - CTL_TABLE_CPU_VARS(8); -#endif -#if NR_CPUS > 9 - CTL_TABLE_CPU_VARS(9); -#endif -#if NR_CPUS > 10 - CTL_TABLE_CPU_VARS(10); -#endif -#if NR_CPUS > 11 - CTL_TABLE_CPU_VARS(11); -#endif -#if NR_CPUS > 12 - CTL_TABLE_CPU_VARS(12); -#endif -#if NR_CPUS > 13 - CTL_TABLE_CPU_VARS(13); -#endif -#if NR_CPUS > 14 - CTL_TABLE_CPU_VARS(14); -#endif -#if NR_CPUS > 15 - CTL_TABLE_CPU_VARS(15); -#endif -#if NR_CPUS > 16 - CTL_TABLE_CPU_VARS(16); -#endif -#if NR_CPUS > 17 - CTL_TABLE_CPU_VARS(17); -#endif -#if NR_CPUS > 18 - CTL_TABLE_CPU_VARS(18); -#endif -#if NR_CPUS > 19 - CTL_TABLE_CPU_VARS(19); -#endif -#if NR_CPUS > 20 - CTL_TABLE_CPU_VARS(20); -#endif -#if NR_CPUS > 21 - CTL_TABLE_CPU_VARS(21); -#endif -#if NR_CPUS > 22 - CTL_TABLE_CPU_VARS(22); -#endif -#if NR_CPUS > 23 - CTL_TABLE_CPU_VARS(23); -#endif -#if NR_CPUS > 24 - CTL_TABLE_CPU_VARS(24); -#endif -#if NR_CPUS > 25 - CTL_TABLE_CPU_VARS(25); -#endif -#if NR_CPUS > 26 - CTL_TABLE_CPU_VARS(26); -#endif -#if NR_CPUS > 27 - CTL_TABLE_CPU_VARS(27); -#endif -#if NR_CPUS > 28 - CTL_TABLE_CPU_VARS(28); -#endif -#if NR_CPUS > 29 - CTL_TABLE_CPU_VARS(29); -#endif -#if NR_CPUS > 30 - CTL_TABLE_CPU_VARS(30); -#endif -#if NR_CPUS > 31 - CTL_TABLE_CPU_VARS(31); -#endif -#if NR_CPUS > 32 -#error please extend CPU enumeration -#endif - -/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ -static ctl_table ctl_cpu_table[NR_CPUS + 1] = { - CPU_ENUM(0), -#if NR_CPUS > 1 - CPU_ENUM(1), -#endif -#if NR_CPUS > 2 - CPU_ENUM(2), -#endif -#if NR_CPUS > 3 - CPU_ENUM(3), -#endif -#if NR_CPUS > 4 - CPU_ENUM(4), -#endif -#if NR_CPUS > 5 - CPU_ENUM(5), -#endif -#if NR_CPUS > 6 - CPU_ENUM(6), -#endif -#if NR_CPUS > 7 - CPU_ENUM(7), -#endif -#if NR_CPUS > 8 - CPU_ENUM(8), -#endif -#if NR_CPUS > 9 - CPU_ENUM(9), -#endif -#if NR_CPUS > 10 - CPU_ENUM(10), -#endif -#if NR_CPUS > 11 - CPU_ENUM(11), -#endif -#if NR_CPUS > 12 - CPU_ENUM(12), -#endif -#if NR_CPUS > 13 - CPU_ENUM(13), -#endif -#if NR_CPUS > 14 - CPU_ENUM(14), -#endif -#if NR_CPUS > 15 - CPU_ENUM(15), -#endif -#if NR_CPUS > 16 - CPU_ENUM(16), -#endif -#if NR_CPUS > 17 - CPU_ENUM(17), -#endif -#if NR_CPUS > 18 - CPU_ENUM(18), -#endif -#if NR_CPUS > 19 - CPU_ENUM(19), -#endif -#if NR_CPUS > 20 - CPU_ENUM(20), -#endif -#if NR_CPUS > 21 - CPU_ENUM(21), -#endif -#if NR_CPUS > 22 - CPU_ENUM(22), -#endif -#if NR_CPUS > 23 - CPU_ENUM(23), -#endif -#if NR_CPUS > 24 - CPU_ENUM(24), -#endif -#if NR_CPUS > 25 - CPU_ENUM(25), -#endif -#if NR_CPUS > 26 - CPU_ENUM(26), -#endif -#if NR_CPUS > 27 - CPU_ENUM(27), -#endif -#if NR_CPUS > 28 - CPU_ENUM(28), -#endif -#if NR_CPUS > 29 - CPU_ENUM(29), -#endif -#if NR_CPUS > 30 - CPU_ENUM(30), -#endif -#if NR_CPUS > 31 - CPU_ENUM(31), -#endif -#if NR_CPUS > 32 -#error please extend CPU enumeration -#endif - { - .ctl_name = 0, - } -}; - -static ctl_table ctl_cpu[2] = { - { - .ctl_name = CTL_CPU, - .procname = "cpu", - .mode = 0555, - .child = ctl_cpu_table, - }, - { - .ctl_name = 0, - } -}; - -struct ctl_table_header *cpufreq_sysctl_table; - -static inline void cpufreq_sysctl_init(void) -{ - cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0); -} - -static inline void cpufreq_sysctl_exit(void) -{ - unregister_sysctl_table(cpufreq_sysctl_table); -} - -#else -#define cpufreq_sysctl_init() do {} while(0) -#define cpufreq_sysctl_exit() do {} while(0) -#endif /* CONFIG_CPU_FREQ_24API */ - - -/************************** sysfs interface ************************/ -static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) -{ - return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); -} - -static ssize_t -store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) -{ - unsigned int freq = 0; - unsigned int ret; - - ret = sscanf (buf, "%u", &freq); - if (ret != 1) - return -EINVAL; - - cpufreq_set(freq, policy->cpu); - - return count; -} - -static struct freq_attr freq_attr_scaling_setspeed = { - .attr = { .name = "scaling_setspeed", .mode = 0644 }, - .show = show_speed, - .store = store_speed, -}; - -static int cpufreq_governor_userspace(struct cpufreq_policy *policy, - unsigned int event) -{ - unsigned int cpu = policy->cpu; - switch (event) { - case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) || - !policy->cur) - return -EINVAL; - down(&userspace_sem); - cpu_is_managed[cpu] = 1; - cpu_min_freq[cpu] = policy->min; - cpu_max_freq[cpu] = policy->max; - cpu_cur_freq[cpu] = policy->cur; - sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); - memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); - up(&userspace_sem); - break; - case CPUFREQ_GOV_STOP: - down(&userspace_sem); - cpu_is_managed[cpu] = 0; - cpu_min_freq[cpu] = 0; - cpu_max_freq[cpu] = 0; - sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); - up(&userspace_sem); - module_put(THIS_MODULE); - break; - case CPUFREQ_GOV_LIMITS: - down(&userspace_sem); - cpu_min_freq[cpu] = policy->min; - cpu_max_freq[cpu] = policy->max; - if (policy->max < cpu_cur_freq[cpu]) - __cpufreq_driver_target(¤t_policy[cpu], policy->max, - CPUFREQ_RELATION_H); - else if (policy->min > cpu_cur_freq[cpu]) - __cpufreq_driver_target(¤t_policy[cpu], policy->min, - CPUFREQ_RELATION_L); - memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); - up(&userspace_sem); - break; - } - return 0; -} - -/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because - * of this, cpu_cur_freq[] needs to be set early. - */ -#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100) -extern unsigned int sa11x0_getspeed(void); - -static void cpufreq_sa11x0_compat(void) -{ - cpu_cur_freq[0] = sa11x0_getspeed(); -} -#else -#define cpufreq_sa11x0_compat() do {} while(0) -#endif - - -static struct cpufreq_governor cpufreq_gov_userspace = { - .name = "userspace", - .governor = cpufreq_governor_userspace, - .owner = THIS_MODULE, -}; -EXPORT_SYMBOL(cpufreq_gov_userspace); - -static int already_init = 0; - -int cpufreq_gov_userspace_init(void) -{ - if (!already_init) { - down(&userspace_sem); - cpufreq_sa11x0_compat(); - cpufreq_sysctl_init(); - cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - already_init = 1; - up(&userspace_sem); - } - return cpufreq_register_governor(&cpufreq_gov_userspace); -} -EXPORT_SYMBOL(cpufreq_gov_userspace_init); - - -static void __exit cpufreq_gov_userspace_exit(void) -{ - cpufreq_unregister_governor(&cpufreq_gov_userspace); - cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - cpufreq_sysctl_exit(); -} - - -MODULE_AUTHOR ("Dominik Brodowski , Russell King "); -MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); -MODULE_LICENSE ("GPL"); - -module_init(cpufreq_gov_userspace_init); -module_exit(cpufreq_gov_userspace_exit); -- cgit v1.2.3 From adff42b1c54cd001d28d4d0ad21127b9be6d4812 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 02:42:28 +0100 Subject: [CPUFREQ] Fix various oddities in the userspace governer. --- drivers/cpufreq/cpufreq_userspace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 7df32a97c50a..9f51fbe9b149 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -498,9 +498,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) || - !policy->cur) + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE))) return -EINVAL; + BUG_ON(!policy->cur); down(&userspace_sem); cpu_is_managed[cpu] = 1; cpu_min_freq[cpu] = policy->min; @@ -551,7 +551,7 @@ static void cpufreq_sa11x0_compat(void) #endif -static struct cpufreq_governor cpufreq_gov_userspace = { +struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, .owner = THIS_MODULE, @@ -587,5 +587,5 @@ MODULE_AUTHOR ("Dominik Brodowski , Russell King Date: Wed, 3 Sep 2003 02:50:10 +0100 Subject: [CPUFREQ] Completely separate governors from policies. Governors are for CPUfreq drivers which have a ->target callback, Policies are for CPUfreq drivers which have a ->setpolicy callback. Also, the "hardwired" governors "powersave" and "performance" are removed. --- drivers/cpufreq/cpufreq.c | 102 +++++++++++++++++++------------------------- drivers/cpufreq/proc_intf.c | 26 +++++------ include/linux/cpufreq.h | 21 +++++++-- 3 files changed, 74 insertions(+), 75 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7f80c321c785..1b037bf0f950 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -109,13 +109,18 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data) int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { - if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_PERFORMANCE; - return 0; - } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_POWERSAVE; - return 0; - } else { + if (!cpufreq_driver) + return -EINVAL; + if (cpufreq_driver->setpolicy) { + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_PERFORMANCE; + return 0; + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_POWERSAVE; + return 0; + } + return -EINVAL; + } else { struct cpufreq_governor *t; down(&cpufreq_governor_sem); if (!cpufreq_driver || !cpufreq_driver->target) @@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { *governor = t; - *policy = CPUFREQ_POLICY_GOVERNOR; up(&cpufreq_governor_sem); return 0; } @@ -190,16 +194,13 @@ store_one(scaling_max_freq,max); */ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) { - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: + if(policy->policy == CPUFREQ_POLICY_POWERSAVE) return sprintf(buf, "powersave\n"); - case CPUFREQ_POLICY_PERFORMANCE: + else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) return sprintf(buf, "performance\n"); - case CPUFREQ_POLICY_GOVERNOR: + else if (policy->governor) return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); - default: - return -EINVAL; - } + return -EINVAL; } @@ -246,15 +247,15 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, ssize_t i = 0; struct cpufreq_governor *t; - i += sprintf(buf, "performance powersave"); - - if (!cpufreq_driver->target) + if (!cpufreq_driver->target) { + i += sprintf(buf, "performance powersave"); goto out; + } list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) goto out; - i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name); + i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } out: i += sprintf(&buf[i], "\n"); @@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) spin_lock_irqsave(&cpufreq_driver_lock, flags); cpufreq_cpu_data[cpu] = policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - + policy->governor = NULL; /* to assure that the starting sequence is + * run in cpufreq_set_policy */ up(&policy->lock); /* set default policy */ + ret = cpufreq_set_policy(&new_policy); if (ret) goto err_out_unregister; @@ -622,33 +625,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { - int ret = 0; + int ret = -EINVAL; - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); - } - break; - case CPUFREQ_POLICY_PERFORMANCE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - } - break; - case CPUFREQ_POLICY_GOVERNOR: - ret = -EINVAL; - if (!try_module_get(policy->governor->owner)) - break; - ret = policy->governor->governor(policy, event); - /* we keep one module reference alive for each CPU governed by this CPU */ - if ((event != CPUFREQ_GOV_START) || ret) - module_put(policy->governor->owner); - if ((event == CPUFREQ_GOV_STOP) && !ret) - module_put(policy->governor->owner); - break; - default: - ret = -EINVAL; - } + if (!try_module_get(policy->governor->owner)) + return -EINVAL; + + ret = policy->governor->governor(policy, event); + + /* we keep one module reference alive for each CPU governed by this CPU */ + if ((event != CPUFREQ_GOV_START) || ret) + module_put(policy->governor->owner); + if ((event == CPUFREQ_GOV_STOP) && !ret) + module_put(policy->governor->owner); return ret; } @@ -680,11 +668,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) if (!governor) return -EINVAL; - if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN)) - return -EBUSY; - if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN)) - return -EBUSY; - down(&cpufreq_governor_sem); list_for_each_entry(t, &cpufreq_governor_list, governor_list) { @@ -808,23 +791,24 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) data->policy = policy->policy; ret = cpufreq_driver->setpolicy(policy); } else { - if ((policy->policy != data->policy) || - ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) { + if (policy->governor != data->governor) { /* save old, working values */ - unsigned int old_pol = data->policy; struct cpufreq_governor *old_gov = data->governor; /* end old governor */ - __cpufreq_governor(data, CPUFREQ_GOV_STOP); + if (data->governor) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); /* start new governor */ - data->policy = policy->policy; data->governor = policy->governor; if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { /* new governor failed, so re-start old one */ - data->policy = old_pol; - data->governor = old_gov; - __cpufreq_governor(data, CPUFREQ_GOV_START); + if (old_gov) { + data->governor = old_gov; + __cpufreq_governor(data, CPUFREQ_GOV_START); + } + ret = -EINVAL; + goto error_out; } /* might be a policy change, too, so fall through */ } diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c index d314e526af9c..b8d6b056051a 100644 --- a/drivers/cpufreq/proc_intf.c +++ b/drivers/cpufreq/proc_intf.c @@ -126,20 +126,20 @@ static int cpufreq_proc_read ( p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ", i , policy.min, min_pctg, policy.max, max_pctg); - switch (policy.policy) { - case CPUFREQ_POLICY_POWERSAVE: - p += sprintf(p, "powersave\n"); - break; - case CPUFREQ_POLICY_PERFORMANCE: - p += sprintf(p, "performance\n"); - break; - case CPUFREQ_POLICY_GOVERNOR: + if (policy.policy) { + switch (policy.policy) { + case CPUFREQ_POLICY_POWERSAVE: + p += sprintf(p, "powersave\n"); + break; + case CPUFREQ_POLICY_PERFORMANCE: + p += sprintf(p, "performance\n"); + break; + default: + p += sprintf(p, "INVALID\n"); + break; + } + } else p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); - break; - default: - p += sprintf(p, "INVALID\n"); - break; - } } end: len = (p - page); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 3d466f6680cb..f920b0a8e83e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); #define CPUFREQ_POLICY_NOTIFIER (1) -/********************** cpufreq policy notifiers *********************/ +/* if (cpufreq_driver->target) exists, the ->governor decides what frequency + * within the limits is used. If (cpufreq_driver->setpolicy> exists, these + * two generic policies are available: + */ #define CPUFREQ_POLICY_POWERSAVE (1) #define CPUFREQ_POLICY_PERFORMANCE (2) -#define CPUFREQ_POLICY_GOVERNOR (3) /* Frequency values here are CPU kHz so that hardware which doesn't run * with some frequencies can complain without having to guess what per @@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event); int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); + /********************************************************************* * CPUFREQ DRIVER INTERFACE * *********************************************************************/ @@ -221,7 +224,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu /********************************************************************* * CPUFREQ USERSPACE GOVERNOR * *********************************************************************/ -extern struct cpufreq_governor cpufreq_gov_userspace; int cpufreq_gov_userspace_init(void); int cpufreq_setmax(unsigned int cpu); @@ -279,6 +281,19 @@ enum { #endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */ +/********************************************************************* + * CPUFREQ DEFAULT GOVERNOR * + *********************************************************************/ + + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE +extern struct cpufreq_governor cpufreq_gov_performance; +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance +#elif CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +extern struct cpufreq_governor cpufreq_gov_userspace; +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace +#endif + /********************************************************************* * FREQUENCY TABLE HELPERS * *********************************************************************/ -- cgit v1.2.3 From 134999da0cf3a1b94802a17af5cd394db489040b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 02:57:16 +0100 Subject: [CPUFREQ] Add the "performance" and "powersave" governors as modules. Also add a config option so that the default governor [which is loaded and enabled at boot] is started. Note that if you select "performance" here, the CPU will be set to the highest possible frequency even if the CPU was booted at a lower frequency. If you select "userspace", the frequency will stay the same. --- drivers/cpufreq/Kconfig | 47 ++++++++++++++++++++++++++++- drivers/cpufreq/Makefile | 2 ++ drivers/cpufreq/cpufreq_performance.c | 57 +++++++++++++++++++++++++++++++++++ drivers/cpufreq/cpufreq_powersave.c | 56 ++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 drivers/cpufreq/cpufreq_performance.c create mode 100644 drivers/cpufreq/cpufreq_powersave.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 88686c3d71f0..0f591d9613ac 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -10,9 +10,54 @@ config CPU_FREQ_PROC_INTF If in doubt, say N. +choice + prompt "Default CPUFreq governor" + depends on CPU_FREQ + default CPU_FREQ_DEFAULT_GOV_PERFORMANCE + help + This option sets which CPUFreq governor shall be loaded at + startup. If in doubt, select 'performance'. + +config CPU_FREQ_DEFAULT_GOV_PERFORMANCE + bool "performance" + select CPU_FREQ_GOV_PERFORMANCE + help + Use the CPUFreq governor 'performance' as default. This sets + the frequency statically to the highest frequency supported by + the CPU. + +config CPU_FREQ_DEFAULT_GOV_USERSPACE + bool "userspace" + select CPU_FREQ_GOV_USERSPACE + help + Use the CPUFreq governor 'userspace' as default. This allows + you to set the CPU frequency manually or when an userspace + programm shall be able to set the CPU dynamically without having + to enable the userspace governor manually. + +endchoice + +config CPU_FREQ_GOV_PERFORMANCE + tristate "'powersave' governor" + depends on CPU_FREQ + help + This cpufreq governors set the frequency statically to the + highest available CPU frequency. + + If in doubt, say Y. + +config CPU_FREQ_GOV_POWERSAVE + tristate "'powersave' governor" + depends on CPU_FREQ + help + Theis cpufreq governors set the frequency statically to the + lowest available CPU frequency. + + If in doubt, say Y. + config CPU_FREQ_GOV_USERSPACE tristate "'userspace' governor for userspace frequency scaling" - depends on CPU_FREQ + depends on CPU_FREQ help Enable this cpufreq governor when you either want to set the CPU frequency manually or when an userspace programm shall diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index e65dca095a53..1eebf3c6edc3 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -2,6 +2,8 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o # CPUfreq governors +obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o +obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o # CPUfreq cross-arch helpers diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c new file mode 100644 index 000000000000..f2348e790569 --- /dev/null +++ b/drivers/cpufreq/cpufreq_performance.c @@ -0,0 +1,57 @@ +/* + * linux/drivers/cpufreq/cpufreq_performance.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +static int cpufreq_governor_performance(struct cpufreq_policy *policy, + unsigned int event) +{ + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_LIMITS: + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + break; + default: + break; + } + return 0; +} + +struct cpufreq_governor cpufreq_gov_performance = { + .name = "performance", + .governor = cpufreq_governor_performance, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(cpufreq_gov_performance); + + +static int __init cpufreq_gov_performance_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_performance); +} + + +static void __exit cpufreq_gov_performance_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_performance); +} + + +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("CPUfreq policy governor 'performance'"); +MODULE_LICENSE("GPL"); + +fs_initcall(cpufreq_gov_performance_init); +module_exit(cpufreq_gov_performance_exit); diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c new file mode 100644 index 000000000000..ec8544885693 --- /dev/null +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -0,0 +1,56 @@ +/* + * linux/drivers/cpufreq/cpufreq_powersave.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +static int cpufreq_governor_powersave(struct cpufreq_policy *policy, + unsigned int event) +{ + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_LIMITS: + __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + break; + default: + break; + } + return 0; +} + +static struct cpufreq_governor cpufreq_gov_powersave = { + .name = "powersave", + .governor = cpufreq_governor_powersave, + .owner = THIS_MODULE, +}; + + +static int __init cpufreq_gov_powersave_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_powersave); +} + + +static void __exit cpufreq_gov_powersave_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_powersave); +} + + +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); +MODULE_LICENSE("GPL"); + +module_init(cpufreq_gov_powersave_init); +module_exit(cpufreq_gov_powersave_exit); -- cgit v1.2.3 From 98a86f6bdb1b49545e0a22f9e0622f757a7d29b2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 03:10:20 +0100 Subject: [CPUFREQ][PPC] Small fixes necessary to separate the governors from policies. --- arch/ppc/platforms/pmac_cpufreq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index a748cb0109db..be861eebab62 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -257,8 +257,7 @@ pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) if (policy->cpu != 0) return -ENODEV; - policy->policy = (cur_freq == low_freq) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = cur_freq; -- cgit v1.2.3 From a62c84600a55c767576e578e5882956c86dd499b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 03:35:15 +0100 Subject: [CPUFREQ][SH] Small fixes necessary to separate the governors from policies. --- arch/sh/kernel/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index 4a5330f0479f..85516164e866 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c @@ -160,7 +160,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) sh_freqs[SH_FREQ_MIN].frequency = min_freq; /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = max_freq; -- cgit v1.2.3 From 4299ec58c70761cc58c1a293581c025649736c47 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 03:47:33 +0100 Subject: [CPUFREQ][SPARC64] Small fixes necessary to separate the governors from policies. --- arch/sparc64/kernel/us2e_cpufreq.c | 2 +- arch/sparc64/kernel/us3_cpufreq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c index 74926fbbe52e..7aae0a18aabe 100644 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ b/arch/sparc64/kernel/us2e_cpufreq.c @@ -309,7 +309,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) table[2].index = 5; table[3].frequency = CPUFREQ_TABLE_END; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c index b5475e7295ef..18fe54b8aa55 100644 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ b/arch/sparc64/kernel/us3_cpufreq.c @@ -163,7 +163,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) table[3].index = 0; table[3].frequency = CPUFREQ_TABLE_END; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; -- cgit v1.2.3 From aca9dc238f1b5598595f93307a0ec220bb11a32b Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Tue, 2 Sep 2003 19:47:52 -0700 Subject: [SCTP] Fix a couple of issues with the call to sctp_ssnmap_new() in sctp_process_init(). The argument passed as inbound streams to sctp_ssnmap_new() is incorrect. Also allocating a ssnmap everytime a INIT is received is vulnerable to DoS attacks. So delay the creation of an ssnmap if we are processing a temporary association. --- net/sctp/sm_make_chunk.c | 13 ++++++++----- net/sctp/socket.c | 10 ++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 44ee598cbe03..40a7a4f7116f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1813,11 +1813,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * stream sequence number shall be set to 0. */ - /* Allocate storage for the negotiated streams. */ - asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams, - asoc->c.sinit_num_ostreams, gfp); - if (!asoc->ssnmap) - goto nomem_ssnmap; + /* Allocate storage for the negotiated streams if it is not a temporary * association. + */ + if (!asoc->temp) { + asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, + asoc->c.sinit_num_ostreams, gfp); + if (!asoc->ssnmap) + goto nomem_ssnmap; + } /* ADDIP Section 4.1 ASCONF Chunk Procedures * diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a071384084eb..63befdba6de2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1435,7 +1435,7 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen) } /* - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -2072,9 +2072,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) return -ESOCKTNOSUPPORT; } - /* FIXME: The next draft (04) of the SCTP Sockets Extensions - * should include a socket option for manipulating these - * message parameters (and a few others). + /* Initialize default send parameters. These parameters can be + * modified with the SCTP_DEFAULT_SEND_PARAM socket option. */ sp->default_stream = 0; sp->default_ppid = 0; @@ -2093,7 +2092,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. - * FIXME: These are not used yet. */ sp->rtoinfo.srto_initial = (sctp_rto_initial / HZ) * 1000; sp->rtoinfo.srto_max = (sctp_rto_max / HZ) * 1000; @@ -2776,7 +2774,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, /* * - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied -- cgit v1.2.3 From e658d4425f0b3cc2a44ddf7c34870bb810b52fd1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 03:53:30 +0100 Subject: [CPUFREQ][X86] Small fixes necessary to separate the governors from policies. --- arch/i386/kernel/cpu/cpufreq/acpi.c | 2 +- arch/i386/kernel/cpu/cpufreq/elanfreq.c | 2 +- arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | 2 +- arch/i386/kernel/cpu/cpufreq/longhaul.c | 2 +- arch/i386/kernel/cpu/cpufreq/longrun.c | 3 ++- arch/i386/kernel/cpu/cpufreq/p4-clockmod.c | 2 +- arch/i386/kernel/cpu/cpufreq/powernow-k6.c | 2 +- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 2 +- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 4 +--- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 3 +-- 10 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c index 36cbb5015deb..2b1e68cb66a6 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c @@ -580,7 +580,7 @@ acpi_cpufreq_cpu_init ( if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency) policy->cpuinfo.transition_latency = perf->states[i].transition_latency; } - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000; /* table init */ diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c index 9214b2e0c360..a15f1ee967ad 100644 --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c @@ -216,7 +216,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) } /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = elanfreq_get_cpu_frequency(); diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 0cec751f8ae8..bb5471e2bc81 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -434,7 +434,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) policy->min = maxfreq / POLICY_MIN_DIV; policy->max = maxfreq; policy->cur = curfreq; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = maxfreq / max_duration; policy->cpuinfo.max_freq = maxfreq; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 808f7f5079b1..1e3de989ac15 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -584,7 +584,7 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) if (ret != 0) return ret; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c index 2adb51a8d3d4..8633cf069d07 100644 --- a/arch/i386/kernel/cpu/cpufreq/longrun.c +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c @@ -120,7 +120,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy) policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - if (policy->policy == CPUFREQ_POLICY_GOVERNOR) + if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && + (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) return -EINVAL; return 0; diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index a1d257e3fa29..4bf4fee0d372 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -211,7 +211,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 1000; policy->cur = stock_freq; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c index 5d967dfe4dbc..bfb2b6b5468c 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c @@ -157,7 +157,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) } /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = busfreq * max_multiplier; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index bf923ee095fe..0f577b37c06c 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -372,7 +372,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", minimum_speed, maximum_speed); - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = latency; policy->cur = maximum_speed; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 19c7821cc15c..2653cc2f3b0c 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -201,9 +201,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) freq = get_cur_freq(); - policy->policy = (freq == centrino_model->max_freq) ? - CPUFREQ_POLICY_PERFORMANCE : - CPUFREQ_POLICY_POWERSAVE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */ policy->cur = freq; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 500b95d66a79..e20b73f4f06f 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -299,8 +299,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) (speed / 1000)); /* cpuinfo and default policy values */ - policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; -- cgit v1.2.3 From c23087dd277880d1426c4489a91d96f79eb31b98 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 04:03:50 +0100 Subject: [CPUFREQ][ARM] allow for easier Kconfig usage on ARM, and more features for SA11x0 users. --- arch/arm/Kconfig | 34 +++++----------------------------- arch/arm/mach-integrator/cpu.c | 2 +- arch/arm/mach-sa1100/cpu-sa1100.c | 2 +- arch/arm/mach-sa1100/cpu-sa1110.c | 2 +- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f4846273df06..31cca56d8e2f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -542,39 +542,15 @@ config CPU_FREQ_SA1100 bool depends on CPU_FREQ && SA1100_LART default y + select CPU_FREQ_DEFAULT_GOV_USERSPACE + select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_SA1110 bool depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) default y - -if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110) - -config CPU_FREQ_GOV_USERSPACE - tristate - depends on CPU_FREQ - default y - -config CPU_FREQ_24_API - bool - depends on CPU_FREQ_GOV_USERSPACE && SYSCTL - default y - -config CPU_FREQ_PROC_INTF - tristate "/proc/cpufreq interface (deprecated)" - depends on CPU_FREQ && PROC_FS - help - This enables the /proc/cpufreq interface for controlling - CPUFreq. Please note that it is recommended to use the sysfs - interface instead (which is built automatically). - - For details, take a look at linux/Documentation/cpufreq. - - If in doubt, say N. - -endif - -# CPUfreq on Integrator can use the generic cpufreq core + select CPU_FREQ_DEFAULT_GOV_USERSPACE + select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_INTEGRATOR tristate "CPUfreq driver for ARM Integrator CPUs" @@ -587,7 +563,7 @@ config CPU_FREQ_INTEGRATOR If in doubt, say Y. -if (CPU_FREQ_INTEGRATOR) +if (CPU_FREQ_INTEGRATOR) || (CPU_FREQ_SA1110) || (CPU_FREQ_SA1100) source "drivers/cpufreq/Kconfig" diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index c14943864287..50eab0a09c11 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -170,7 +170,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy) vco.r = 22; /* set default policy and cpuinfo */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.max_freq = 160000; policy->cpuinfo.min_freq = 12000; policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */ diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index f71a28cdcf26..2ec95ad1db47 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -222,7 +222,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) if (policy->cpu != 0) return -EINVAL; policy->cur = policy->min = policy->max = sa11x0_getspeed(); - policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 87a0d789e34a..fd1092e4939c 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -317,7 +317,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) if (policy->cpu != 0) return -EINVAL; policy->cur = policy->min = policy->max = sa11x0_getspeed(); - policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; -- cgit v1.2.3 From 4eaf274524e1e5a3cd3111ad1aba313a0b7bf494 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 04:14:06 +0100 Subject: [CPUFREQ] Fix incorrect entry in Kconfig --- drivers/cpufreq/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 0f591d9613ac..d6fc18d3c927 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -38,7 +38,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE endchoice config CPU_FREQ_GOV_PERFORMANCE - tristate "'powersave' governor" + tristate "'performance' governor" depends on CPU_FREQ help This cpufreq governors set the frequency statically to the -- cgit v1.2.3 From c2d0c666a4683fb5c06de6b9ebf470bd97c1430b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 04:19:46 +0100 Subject: [CPUFREQ] new cpufreq_driver->resume callback, needed (at least) for speedstep-smi. --- Documentation/cpu-freq/cpu-drivers.txt | 6 ++++++ drivers/cpufreq/cpufreq.c | 13 +++++++++++++ include/linux/cpufreq.h | 1 + 3 files changed, 20 insertions(+) diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index bf4c682bc696..43c743903dd7 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -64,6 +64,12 @@ And optionally cpufreq_driver.exit - A pointer to a per-CPU cleanup function. +cpufreq_driver.resume - A pointer to a per-CPU resume function + which is called with interrupts disabled + and _before_ the pre-suspend frequency + and/or policy is restored by a call to + ->target or ->setpolicy. + cpufreq_driver.attr - A pointer to a NULL-terminated list of "struct freq_attr" which allow to export values to sysfs. diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1b037bf0f950..04cfcc54fa1f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -495,6 +495,13 @@ static int cpufreq_resume(struct sys_device * sysdev) if (!cpu_policy) return -EINVAL; + if (cpufreq_driver->resume) + ret = cpufreq_driver->resume(cpu_policy); + if (ret) { + printk(KERN_ERR "cpufreq: resume failed in ->resume step on CPU %u\n", cpu_policy->cpu); + goto out; + } + if (cpufreq_driver->setpolicy) ret = cpufreq_driver->setpolicy(cpu_policy); else @@ -503,6 +510,12 @@ static int cpufreq_resume(struct sys_device * sysdev) */ ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H); + if (ret) { + printk(KERN_ERR "cpufreq: resume failed in ->setpolicy/target step on CPU %u\n", cpu_policy->cpu); + goto out; + } + + out: cpufreq_cpu_put(cpu_policy); return ret; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index f920b0a8e83e..f747117285f4 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -179,6 +179,7 @@ struct cpufreq_driver { /* optional */ int (*exit) (struct cpufreq_policy *policy); + int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; }; -- cgit v1.2.3 From 27cb24a7b7ab09d834bdc17479e9d9f8df8c9c51 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 04:27:43 +0100 Subject: [CPUFREQ] fix speedstep-ich's .name to reflect its real name --- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index e20b73f4f06f..aeeaefd33789 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -308,7 +308,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver speedstep_driver = { - .name = "speedstep", + .name = "speedstep-ich", .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, -- cgit v1.2.3 From 6404c85bc35379948e5368a75d2df714832eb9bb Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 04:54:08 +0100 Subject: [CPUFREQ] Inform user about broken powernow-k7 PST tables. --- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 0f577b37c06c..c0b9bf22b7e9 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -1,6 +1,7 @@ /* * AMD K7 Powernow driver. * (C) 2003 Dave Jones on behalf of SuSE Labs. + * (C) 2003 Dave Jones * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. @@ -325,6 +326,8 @@ static int powernow_decode_bios (int maxfid, int startvid) p+=2; } } + printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple); + printk ("This is indicative of a broken BIOS. Email davej@redhat.com\n"); return -EINVAL; } p++; -- cgit v1.2.3 From 16321c0bb7263952a20a98ac7eca67e55baeaaae Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Tue, 2 Sep 2003 21:06:16 -0700 Subject: [SCTP] draft 07 API changes: Disable listening when backlog is 0. --- net/sctp/socket.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 63befdba6de2..624ea882f1b1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3346,9 +3346,19 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) if (!sctp_style(sk, UDP)) return -EINVAL; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + + /* Return if we are already listening. */ if (sctp_sstate(sk, LISTENING)) return 0; - + /* * If a bind() or sctp_bindx() is not called prior to a listen() * call that allows new associations to be accepted, the system @@ -3379,6 +3389,15 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + if (sctp_sstate(sk, LISTENING)) return 0; -- cgit v1.2.3 From f534e7fca196d0985c00adb5278bec2cd850777e Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Wed, 3 Sep 2003 02:16:24 -0700 Subject: [SCTP] draft 07 API changes: By default, all the event notifications are turned off even for one-to-many style sockets. --- net/sctp/socket.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 624ea882f1b1..7843838b698a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2107,15 +2107,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->assocparams.sasoc_cookie_life = (sctp_valid_cookie_life / HZ) * 1000; - /* Initialize default event subscriptions. - * the struct sock is initialized to zero, so only - * enable the events needed. By default, UDP-style - * sockets enable io and association change notifications. + /* Initialize default event subscriptions. By default, all the + * options are off. */ - if (sctp_style(sk, UDP)) { - sp->subscribe.sctp_data_io_event = 1; - sp->subscribe.sctp_association_event = 1; - } + memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); /* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS -- cgit v1.2.3 From ba27a6f2ccd3c964ab3d01636636908b1a7b0f12 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Sep 2003 18:45:31 +0100 Subject: [AGPGART] Fix up compile for i460-agp Missed conversion when killing off the APBASE defines. --- drivers/char/agp/i460-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 336fdda5fe91..2f70f417f221 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -128,7 +128,7 @@ static int i460_fetch_size (void) if (temp & I460_BAPBASE_ENABLE) i460.dynamic_apbase = INTEL_I460_BAPBASE; else - i460.dynamic_apbase = INTEL_I460_APBASE; + i460.dynamic_apbase = AGP_APBASE; for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* -- cgit v1.2.3 From bf228be377ade952ed0feea3f2e96a8701069902 Mon Sep 17 00:00:00 2001 From: John Levon Date: Wed, 3 Sep 2003 17:54:03 -0700 Subject: [NET]: Kill net/README, obsolete and out-of-date. --- net/README | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 net/README diff --git a/net/README b/net/README deleted file mode 100644 index e509ec526c25..000000000000 --- a/net/README +++ /dev/null @@ -1,26 +0,0 @@ - -Maintainers and developers for networking code sections - -Code Section Bug Report Contact --------------------+------------------------------------------- -802 [other ] alan@lxorguk.ukuu.org.uk - [token ring ] p.norton@computer.org -appletalk jschlst@samba.org -ax25 g4klx@g4klx.demon.co.uk -bridge buytenh@gnu.org -core alan@lxorguk.ukuu.org.uk -decnet SteveW@ACM.org -ethernet alan@lxorguk.ukuu.org.uk -ipv4 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipv6 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipx acme@conectiva.com.br -spx jschlst@samba.org -irda dagb@cs.uit.no -lapb g4klx@g4klx.demon.co.uk -netrom g4klx@g4klx.demon.co.uk -rose g4klx@g4klx.demon.co.uk -wanrouter gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com -unix alan@lxorguk.ukuu.org.uk -x25 g4klx@g4klx.demon.co.uk -bluetooth maxk@qualcomm.com -8021q greearb@candelatech.com, vlan@scry.wanfear.com -- cgit v1.2.3 From 440f48e73cc0d64cd48c07dbf3195c06a122bb1c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 03:24:52 +0100 Subject: [CPUFREQ] Cache FSB in longhaul driver. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 1e3de989ac15..6043aa322f5d 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -256,16 +256,16 @@ static struct cpufreq_frequency_table *longhaul_table; static int longhaul_get_cpu_fsb (void) { + unsigned long lo, hi; unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; - unsigned long invalue=0,lo, hi; + unsigned int invalue=0; if (fsb == 0) { rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; - return eblcr_fsb_table[invalue]; - } else { - return fsb; + fsb = eblcr_fsb_table[invalue]; } + return fsb; } -- cgit v1.2.3 From a69aa1564d4972ba278b1c21f603ca21533de871 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 03:48:51 +0100 Subject: [CPUFREQ] Fix use of fsb before initialisation in longhaul. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 6043aa322f5d..f7e778d90f4c 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -254,7 +254,7 @@ static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; -static int longhaul_get_cpu_fsb (void) +static unsigned int longhaul_get_cpu_fsb (void) { unsigned long lo, hi; unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; @@ -403,6 +403,8 @@ static int __init longhaul_get_ranges (void) unsigned int j, k = 0; union msr_longhaul longhaul; + fsb = longhaul_get_cpu_fsb(); + switch (longhaul_version) { case 1: /* Ugh, Longhaul v1 didn't have the min/max MSRs. -- cgit v1.2.3 From 2798b95deb1483973b5b0d7e7849981784d8303e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 04:23:31 +0100 Subject: [CPUFREQ] Fix longhaul's mult,fsb -> MHz conversions. this was wrong in several places by a factor of 100. Introduce a calc_speed helper to make this harder to get wrong. Additionally, clean up some printk's to print out useful values like MinMult=3.5x instead of MinMult(x10)=35. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 38 +++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index f7e778d90f4c..ced5f1e67a58 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -254,6 +254,12 @@ static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; +static unsigned int calc_speed (int mult, int fsb) +{ + return ((mult/10)*fsb) + ((mult%10)*(fsb/2)); +} + + static unsigned int longhaul_get_cpu_fsb (void) { unsigned long lo, hi; @@ -292,7 +298,7 @@ static int longhaul_get_cpu_mult (void) static void longhaul_setstate (unsigned int clock_ratio_index) { - int vidindex, i; + int vidindex, i, speed, mult; struct cpufreq_freqs freqs; union msr_longhaul longhaul; union msr_bcr2 bcr2; @@ -300,18 +306,19 @@ static void longhaul_setstate (unsigned int clock_ratio_index) if (clock_ratio[clock_ratio_index] == -1) return; - if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) || - ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed)) + mult = clock_ratio[clock_ratio_index]; + speed = calc_speed (mult, fsb); + if ((speed > highest_speed) || (speed < lowest_speed)) return; - freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100; - freqs.new = clock_ratio[clock_ratio_index] * fsb * 100; + freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb); + freqs.new = speed; freqs.cpu = 0; /* longhaul.c is UP only driver */ - + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO PFX "FSB:%d Mult(x10):%d\n", - fsb * 100, clock_ratio[clock_ratio_index]); + dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, + mult/10, mult%10); switch (longhaul_version) { case 1: @@ -432,11 +439,11 @@ static int __init longhaul_get_ranges (void) break; } - highest_speed = maxmult * fsb * 100; - lowest_speed = minmult * fsb * 100; - dprintk (KERN_INFO PFX "MinMult(x10)=%d MaxMult(x10)=%d\n", - minmult, maxmult); - dprintk (KERN_INFO PFX "Lowestspeed=%d Highestspeed=%d\n", + dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", + minmult/10, minmult%10, maxmult/10, maxmult%10); + highest_speed = calc_speed (maxmult, fsb); + lowest_speed = calc_speed (minmult,fsb); + dprintk (KERN_INFO PFX "Lowestspeed=%dMHz Highestspeed=%dMHz\n", lowest_speed, highest_speed); longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); @@ -448,7 +455,7 @@ static int __init longhaul_get_ranges (void) continue; if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult)) continue; - longhaul_table[k].frequency= clock_ratio[j] * fsb * 100; + longhaul_table[k].frequency = calc_speed (clock_ratio[j], fsb); longhaul_table[k].index = (j << 8); k++; } @@ -588,8 +595,7 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - - policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); + policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); } -- cgit v1.2.3 From 76374783455031bc6d997c8bed4cbce9e7a7a509 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 04:38:00 +0100 Subject: [CPUFREQ] Clean up clock_ratio calculation. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ced5f1e67a58..9b851aea777b 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -303,10 +303,10 @@ static void longhaul_setstate (unsigned int clock_ratio_index) union msr_longhaul longhaul; union msr_bcr2 bcr2; - if (clock_ratio[clock_ratio_index] == -1) + mult = clock_ratio[clock_ratio_index]; + if (mult == -1) return; - mult = clock_ratio[clock_ratio_index]; speed = calc_speed (mult, fsb); if ((speed > highest_speed) || (speed < lowest_speed)) return; @@ -450,12 +450,14 @@ static int __init longhaul_get_ranges (void) if(!longhaul_table) return -ENOMEM; - for (j=0; (j maxmult) || ((unsigned int)clock_ratio[j] < minmult)) + if (ratio > maxmult || ratio < minmult) continue; - longhaul_table[k].frequency = calc_speed (clock_ratio[j], fsb); + longhaul_table[k].frequency = calc_speed (ratio, fsb); longhaul_table[k].index = (j << 8); k++; } -- cgit v1.2.3 From e2495f06ef2c6f01f65fc0f722d5c6e97a00f2e2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 04:51:33 +0100 Subject: [CPUFREQ] Inform user of status of Ezra-T/Nehemiah longhaul support. These are currently unsupported, and I get quite a lot of mails asking about it. Hopefully this will be a little more informative than 'unknown CPU'. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 9b851aea777b..a8271b30e41c 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -577,7 +577,6 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) break; case 8: /* C5M/C5N */ - return -ENODEV; // Waiting on updated docs from VIA before this is usable longhaul_version=3; numscales=32; memcpy (clock_ratio, longhaul3_clock_ratio, sizeof(longhaul3_clock_ratio)); @@ -614,14 +613,20 @@ static int __init longhaul_init (void) { struct cpuinfo_x86 *c = cpu_data; - if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) ) + if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) return -ENODEV; switch (c->x86_model) { case 6 ... 7: return cpufreq_register_driver(&longhaul_driver); case 8: - return -ENODEV; + printk (KERN_INFO PFX "Ezra-T unsupported: Waiting on updated docs " + "from VIA before this is usable.\n"); + break; + case 9: + printk (KERN_INFO PFX "Nehemiah unsupported: Waiting on working silicon " + "from VIA before this is usable.\n"); + break; default: printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n"); } -- cgit v1.2.3 From f1e5737b00d13a9432e1d50ea961f9a10cd707d7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 05:02:49 +0100 Subject: [CPUFREQ] Remove the voltage scaling from longhaul driver. The 'match voltage to frequency' routine is complete crap and needs rewriting. (It also only works for a single stepping of C3) I'll redo it when I find the specs again. In the meantime, it doesn't work properly, so kill it. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 44 +++++++++++---------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index a8271b30e41c..0725e4120a28 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -298,7 +298,7 @@ static int longhaul_get_cpu_mult (void) static void longhaul_setstate (unsigned int clock_ratio_index) { - int vidindex, i, speed, mult; + int speed, mult; struct cpufreq_freqs freqs; union msr_longhaul longhaul; union msr_bcr2 bcr2; @@ -336,6 +336,14 @@ static void longhaul_setstate (unsigned int clock_ratio_index) wrmsrl (MSR_VIA_BCR2, bcr2.val); break; + /* + * Longhaul v2. (Ezra [C5C]) + * We can scale voltage with this too, but that's currently + * disabled until we come up with a decent 'match freq to voltage' + * algorithm. + * We also need to do the voltage/freq setting in order depending + * on the direction of scaling (like we do in powernow-k7.c) + */ case 2: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; @@ -344,39 +352,16 @@ static void longhaul_setstate (unsigned int clock_ratio_index) /* We must program the revision key only with values we * know about, not blindly copy it from 0:3 */ longhaul.bits.RevisionKey = 1; - - if (can_scale_voltage) { - /* PB: TODO fix this up */ - vidindex = (((highest_speed-lowest_speed) / (fsb/2)) - - ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2))); - for (i=0;i<32;i++) { - dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n", - minvid+(vidindex*25), voltage_table[i]); - if (voltage_table[i]==(minvid + (vidindex * 25))) - break; - } - if (i==32) - goto bad_voltage; - - dprintk (KERN_INFO PFX "Desired vid index=%d\n", i); -#if 0 - longhaul.bits.SoftVID = i; - longhaul.bits.EnableSoftVID = 1; -#endif - } -/* FIXME: Do voltage and freq seperatly like we do in powernow-k7 */ -bad_voltage: wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); __hlt(); - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.EnableSoftBusRatio = 0; - if (can_scale_voltage) - longhaul.bits.EnableSoftVID = 0; - longhaul.bits.RevisionKey = 1; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); break; + /* + * Longhaul v3. (Ezra-T [C5M], Nehemiag [C5N]) + * This can also do voltage scaling, but see above. + * Ezra-T was alleged to do FSB scaling too, but it never worked in practice. + */ case 3: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; @@ -385,7 +370,6 @@ bad_voltage: /* We must program the revision key only with values we * know about, not blindly copy it from 0:3 */ longhaul.bits.RevisionKey = 3; /* SoftVID & SoftBSEL */ - wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); __hlt(); -- cgit v1.2.3 From 4e5f89d212425aa84282357c17e8fa45f07f7519 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Wed, 3 Sep 2003 21:08:15 -0700 Subject: [ATM]: Convert the /proc/net/atm/br2684 to seq_file interface (from shemminger@osdl.org) --- net/atm/br2684.c | 137 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 65 deletions(-) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fa25cbdd9a80..0f9d98463a69 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -18,6 +18,7 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include #include #include +#include #include @@ -666,31 +667,57 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* Never put more than 256 bytes in at once */ -static int br2684_proc_engine(loff_t pos, char *buf) +#ifdef CONFIG_PROC_FS +static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) { - struct list_head *lhd, *lhc; - struct net_device *net_dev; - struct br2684_dev *brdev; - struct br2684_vcc *brvcc; - list_for_each(lhd, &br2684_devs) { - net_dev = list_entry_brdev(lhd); - brdev = BRPRIV(net_dev); - if (pos-- == 0) - return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" - "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, - brdev->number, - net_dev->dev_addr[0], - net_dev->dev_addr[1], - net_dev->dev_addr[2], - net_dev->dev_addr[3], - net_dev->dev_addr[4], - net_dev->dev_addr[5], - brdev->mac_was_set ? "set" : "auto"); - list_for_each(lhc, &brdev->brvccs) { - brvcc = list_entry_brvcc(lhc); - if (pos-- == 0) - return sprintf(buf, " vcc %d.%d.%d: encaps=%s" + loff_t offs = 0; + struct br2684_dev *brd; + + read_lock(&devs_lock); + + list_for_each_entry(brd, &br2684_devs, br2684_devs) { + if (offs == *pos) + return brd; + ++offs; + } + return NULL; +} + +static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct br2684_dev *brd = v; + + ++*pos; + + brd = list_entry(brd->br2684_devs.next, + struct br2684_dev, br2684_devs); + return (&brd->br2684_devs != &br2684_devs) ? brd : NULL; +} + +static void br2684_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&devs_lock); +} + +static int br2684_seq_show(struct seq_file *seq, void *v) +{ + const struct br2684_dev *brdev = v; + const struct net_device *net_dev = brdev->net_dev; + const struct br2684_vcc *brvcc; + + seq_printf(seq, "dev %.16s: num=%d, mac=%02X:%02X:" + "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, + brdev->number, + net_dev->dev_addr[0], + net_dev->dev_addr[1], + net_dev->dev_addr[2], + net_dev->dev_addr[3], + net_dev->dev_addr[4], + net_dev->dev_addr[5], + brdev->mac_was_set ? "set" : "auto"); + + list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { + seq_printf(seq, " vcc %d.%d.%d: encaps=%s" #ifndef FASTER_VERSION ", failed copies %u/%u" #endif /* FASTER_VERSION */ @@ -711,63 +738,41 @@ static int br2684_proc_engine(loff_t pos, char *buf) #undef bs #undef b1 #endif /* CONFIG_ATM_BR2684_IPFILTER */ - } } return 0; } -static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, - loff_t *pos) +static struct seq_operations br2684_seq_ops = { + .start = br2684_seq_start, + .next = br2684_seq_next, + .stop = br2684_seq_stop, + .show = br2684_seq_show, +}; + +static int br2684_proc_open(struct inode *inode, struct file *file) { - unsigned long page; - int len = 0, x, left; - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - left = PAGE_SIZE - 256; - if (count < left) - left = count; - read_lock(&devs_lock); - for (;;) { - x = br2684_proc_engine(*pos, &((char *) page)[len]); - if (x == 0) - break; - if (x > left) - /* - * This should only happen if the user passed in - * a "count" too small for even one line - */ - x = -EINVAL; - if (x < 0) { - len = x; - break; - } - len += x; - left -= x; - (*pos)++; - if (left < 256) - break; - } - read_unlock(&devs_lock); - if (len > 0 && copy_to_user(buf, (char *) page, len)) - len = -EFAULT; - free_page(page); - return len; + return seq_open(file, &br2684_seq_ops); } -static struct file_operations br2684_proc_operations = { - .owner = THIS_MODULE, - .read = br2684_proc_read, +static struct file_operations br2684_proc_ops = { + .owner = THIS_MODULE, + .open = br2684_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ +#endif static int __init br2684_init(void) { +#ifdef CONFIG_PROC_FS struct proc_dir_entry *p; if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) return -ENOMEM; - p->proc_fops = &br2684_proc_operations; + p->proc_fops = &br2684_proc_ops; +#endif br2684_ioctl_set(br2684_ioctl); return 0; } @@ -779,7 +784,9 @@ static void __exit br2684_exit(void) struct br2684_vcc *brvcc; br2684_ioctl_set(NULL); +#ifdef CONFIG_PROC_FS remove_proc_entry("br2684", atm_proc_root); +#endif while (!list_empty(&br2684_devs)) { net_dev = list_entry_brdev(br2684_devs.next); -- cgit v1.2.3 From 11edb4ad74e0307ffa915d9739f7bb89283a29c1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Sep 2003 05:23:06 +0100 Subject: [CPUFREQ] Move longhaul scale/ratio tables to longhaul header file --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 191 ------------------------------ arch/i386/kernel/cpu/cpufreq/longhaul.h | 201 ++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 191 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 0725e4120a28..7bc5d8309bc9 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -54,197 +54,6 @@ static unsigned int fsb; #define __hlt() __asm__ __volatile__("hlt": : :"memory") -/* - * Clock ratio tables. - * The eblcr ones specify the ratio read from the CPU. - * The clock_ratio ones specify what to write to the CPU. - */ - -/* VIA C3 Samuel 1 & Samuel 2 (stepping 0)*/ -static int __initdata longhaul1_clock_ratio[16] = { - -1, /* 0000 -> RESERVED */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - -1, /* 0011 -> RESERVED */ - -1, /* 0100 -> RESERVED */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - -1, /* 1110 -> RESERVED */ - -1, /* 1111 -> RESERVED */ -}; - -static int __initdata samuel1_eblcr[16] = { - 50, /* 0000 -> RESERVED */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - -1, /* 0011 -> RESERVED */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - -1, /* 0111 -> RESERVED */ - -1, /* 1000 -> RESERVED */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - -1, /* 1100 -> RESERVED */ - 75, /* 1101 -> 7.5x */ - -1, /* 1110 -> RESERVED */ - 65, /* 1111 -> 6.5x */ -}; - -/* VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra */ -static int __initdata longhaul2_clock_ratio[16] = { - 100, /* 0000 -> 10.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 90, /* 0011 -> 9.0x */ - 95, /* 0100 -> 9.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 120, /* 1111 -> 12.0x */ -}; - -static int __initdata samuel2_eblcr[16] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 110, /* 0111 -> 11.0x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 130, /* 1110 -> 13.0x */ - 65, /* 1111 -> 6.5x */ -}; - -static int __initdata ezra_eblcr[16] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 95, /* 0111 -> 9.5x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 65, /* 1111 -> 6.5x */ -}; - -/* VIA C5M. */ -static int __initdata longhaul3_clock_ratio[32] = { - 100, /* 0000 -> 10.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 90, /* 0011 -> 9.0x */ - 95, /* 0100 -> 9.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 120, /* 1111 -> 12.0x */ - - -1, /* 0000 -> RESERVED (10.0x) */ - 110, /* 0001 -> 11.0x */ - 120, /* 0010 -> 12.0x */ - -1, /* 0011 -> RESERVED (9.0x)*/ - 105, /* 0100 -> 10.5x */ - 115, /* 0101 -> 11.5x */ - 125, /* 0110 -> 12.5x */ - 135, /* 0111 -> 13.5x */ - 140, /* 1000 -> 14.0x */ - 150, /* 1001 -> 15.0x */ - 160, /* 1010 -> 16.0x */ - 130, /* 1011 -> 13.0x */ - 145, /* 1100 -> 14.5x */ - 155, /* 1101 -> 15.5x */ - -1, /* 1110 -> RESERVED (13.0x) */ - -1, /* 1111 -> RESERVED (12.0x) */ -}; - -static int __initdata c5m_eblcr[32] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 95, /* 0111 -> 9.5x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 65, /* 1111 -> 6.5x */ - - -1, /* 0000 -> RESERVED (9.0x) */ - 110, /* 0001 -> 11.0x */ - 120, /* 0010 -> 12.0x */ - -1, /* 0011 -> RESERVED (10.0x)*/ - 135, /* 0100 -> 13.5x */ - 115, /* 0101 -> 11.5x */ - 125, /* 0110 -> 12.5x */ - 105, /* 0111 -> 10.5x */ - 130, /* 1000 -> 13.0x */ - 150, /* 1001 -> 15.0x */ - 160, /* 1010 -> 16.0x */ - 140, /* 1011 -> 14.0x */ - -1, /* 1100 -> RESERVED (12.0x) */ - 155, /* 1101 -> 15.5x */ - -1, /* 1110 -> RESERVED (13.0x) */ - 145, /* 1111 -> 14.5x */ -}; - -/* Voltage scales. Div by 1000 to get actual voltage. */ -static int __initdata vrm85scales[32] = { - 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, - 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, - 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, - 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, -}; - -static int __initdata mobilevrmscales[32] = { - 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, - 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, - 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, - 1075, 1050, 1025, 1000, 975, 950, 925, -1, -}; - /* Clock ratios multiplied by 10 */ static int clock_ratio[32]; static int eblcr_table[32]; diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h index 3070d708cb56..f4d4a472b449 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.h +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h @@ -47,3 +47,204 @@ union msr_longhaul { unsigned long long val; }; +/* + * Clock ratio tables. Div/Mod by 10 to get ratio. + * The eblcr ones specify the ratio read from the CPU. + * The clock_ratio ones specify what to write to the CPU. + */ + +/* + * VIA C3 Samuel 1 & Samuel 2 (stepping 0) + */ +static int __initdata longhaul1_clock_ratio[16] = { + -1, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + -1, /* 0100 -> RESERVED */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + -1, /* 1111 -> RESERVED */ +}; + +static int __initdata samuel1_eblcr[16] = { + 50, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + -1, /* 0111 -> RESERVED */ + -1, /* 1000 -> RESERVED */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + -1, /* 1100 -> RESERVED */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + 65, /* 1111 -> 6.5x */ +}; + +/* + * VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra + */ +static int __initdata longhaul2_clock_ratio[16] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ +}; + +static int __initdata samuel2_eblcr[16] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 110, /* 0111 -> 11.0x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 130, /* 1110 -> 13.0x */ + 65, /* 1111 -> 6.5x */ +}; + +static int __initdata ezra_eblcr[16] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ +}; + +/* + * VIA C3 (Ezra-T) [C5M]. + */ +static int __initdata longhaul3_clock_ratio[32] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ + + -1, /* 0000 -> RESERVED (10.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (9.0x)*/ + 105, /* 0100 -> 10.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 135, /* 0111 -> 13.5x */ + 140, /* 1000 -> 14.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 130, /* 1011 -> 13.0x */ + 145, /* 1100 -> 14.5x */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + -1, /* 1111 -> RESERVED (12.0x) */ +}; + +static int __initdata c5m_eblcr[32] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ + + -1, /* 0000 -> RESERVED (9.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (10.0x)*/ + 135, /* 0100 -> 13.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 105, /* 0111 -> 10.5x */ + 130, /* 1000 -> 13.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 140, /* 1011 -> 14.0x */ + -1, /* 1100 -> RESERVED (12.0x) */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + 145, /* 1111 -> 14.5x */ +}; + + +/* + * Voltage scales. Div/Mod by 1000 to get actual voltage. + * Which scale to use depends on the VRM type in use. + */ +static int __initdata vrm85scales[32] = { + 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, + 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, + 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, + 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, +}; + +static int __initdata mobilevrmscales[32] = { + 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, + 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, + 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, + 1075, 1050, 1025, 1000, 975, 950, 925, -1, +}; + -- cgit v1.2.3 From fb06b8eebfcfba5bb21de79f01530c168fb91a76 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 22:03:29 -0700 Subject: [NET]: Convert /proc/net/unix to seq_file. --- net/unix/af_unix.c | 136 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d9dd8a2f3914..1a3873145535 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -111,6 +111,7 @@ #include #include #include +#include #include #include #include @@ -1805,25 +1806,52 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl #ifdef CONFIG_PROC_FS -static int unix_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static struct sock *unix_seq_idx(int *iter, loff_t pos) { - off_t pos=0; - off_t begin=0; - int len=0; - int i; + loff_t off = 0; struct sock *s; - - len+= sprintf(buffer,"Num RefCount Protocol Flags Type St " - "Inode Path\n"); + for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) { + if (off == pos) + return s; + ++off; + } + return NULL; +} + + +static void *unix_seq_start(struct seq_file *seq, loff_t *pos) +{ read_lock(&unix_table_lock); - forall_unix_sockets (i,s) - { + return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1); +} + +static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + if (v == (void *)1) + return first_unix_socket(seq->private); + return next_unix_socket(seq->private, v); +} + +static void unix_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&unix_table_lock); +} + +static int unix_seq_show(struct seq_file *seq, void *v) +{ + + if (v == (void *)1) + seq_puts(seq, "Num RefCount Protocol Flags Type St " + "Inode Path\n"); + else { + struct sock *s = v; struct unix_sock *u = unix_sk(s); unix_state_rlock(s); - len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5lu", + seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", s, atomic_read(&s->sk_refcnt), 0, @@ -1835,39 +1863,61 @@ static int unix_read_proc(char *buffer, char **start, off_t offset, sock_i_ino(s)); if (u->addr) { - buffer[len++] = ' '; - memcpy(buffer+len, u->addr->name->sun_path, - u->addr->len-sizeof(short)); - if (!UNIX_ABSTRACT(s)) - len--; - else - buffer[len] = '@'; - len += u->addr->len - sizeof(short); - } - unix_state_runlock(s); + int i; + seq_putc(seq, ' '); + + for (i = 0; i < u->addr->len-sizeof(short); i++) + seq_putc(seq, u->addr->name->sun_path[i]); - buffer[len++]='\n'; - - pos = begin + len; - if(posoffset+length) - goto done; + unix_state_runlock(s); + seq_putc(seq, '\n'); } - *eof = 1; -done: - read_unlock(&unix_table_lock); - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if (len < 0) - len = 0; - return len; + + return 0; +} + +struct seq_operations unix_seq_ops = { + .start = unix_seq_start, + .next = unix_seq_next, + .stop = unix_seq_stop, + .show = unix_seq_show, +}; + + +static int unix_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + int *iter = kmalloc(sizeof(int), GFP_KERNEL); + + if (!iter) + goto out; + + rc = seq_open(file, &unix_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = iter; + *iter = 0; +out: + return rc; +out_kfree: + kfree(iter); + goto out; } + +static struct file_operations unix_seq_fops = { + .owner = THIS_MODULE, + .open = unix_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + #endif struct proto_ops unix_stream_ops = { @@ -1947,7 +1997,7 @@ static int __init af_unix_init(void) sock_register(&unix_family_ops); #ifdef CONFIG_PROC_FS - create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); + proc_net_fops_create("unix", 0, &unix_seq_fops); #endif unix_sysctl_register(); return 0; @@ -1957,7 +2007,7 @@ static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); unix_sysctl_unregister(); - remove_proc_entry("net/unix", 0); + proc_net_remove("unix"); kmem_cache_destroy(unix_sk_cachep); } -- cgit v1.2.3 From 4a542137c484ae008f3e185f819b8800f9bcc21f Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Wed, 3 Sep 2003 22:36:38 -0700 Subject: [SCTP] Move a local variable declaration ahead of the function code. Apparently the new gcc 3.2.2 allows local variable declarations within the code of a function if it is not used earlier. But older gcc's do not allow this. --- net/sctp/bind_addr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index fa51ddefa3e0..c2a288bcca39 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) Cisco 1999,2000 * Copyright (c) Motorola 1999,2000,2001 - * Copyright (c) International Business Machines Corp., 2001,2002 * Copyright (c) La Monte H.P. Yarroll 2001 * * This file is part of the SCTP kernel reference implementation. @@ -223,9 +223,10 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int len; struct sctp_sockaddr_entry *addr; struct list_head *pos; + struct sctp_af *af; + addrparms_len = 0; len = 0; - struct sctp_af *af; /* Allocate enough memory at once. */ list_for_each(pos, &bp->address_list) { -- cgit v1.2.3 From 8697648c34930bb48cfc40785688cd73a3e7269c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 4 Sep 2003 09:02:39 -0700 Subject: [CRYPTO]: Use try_then_request_module(). try_then_request_module() does what crypto/autoload.c is doing, so replace it. Fix try_then_request_module(), too (thanks James). --- crypto/Makefile | 3 +-- crypto/autoload.c | 37 ------------------------------------- crypto/internal.h | 10 ++++------ include/linux/kmod.h | 2 +- 4 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 crypto/autoload.c diff --git a/crypto/Makefile b/crypto/Makefile index f3325db1ee76..8326b4fb5be4 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -2,11 +2,10 @@ # Cryptographic API # -autoload-crypto-$(CONFIG_KMOD) = autoload.o proc-crypto-$(CONFIG_PROC_FS) = proc.o obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ - $(autoload-crypto-y) $(proc-crypto-y) + $(proc-crypto-y) obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o diff --git a/crypto/autoload.c b/crypto/autoload.c deleted file mode 100644 index 7cda40b39ddf..000000000000 --- a/crypto/autoload.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Cryptographic API. - * - * Algorithm autoloader. - * - * Copyright (c) 2002 James Morris - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ -#include -#include -#include -#include -#include "internal.h" - -/* - * A far more intelligent version of this is planned. For now, just - * try an exact match on the name of the algorithm. - */ -void crypto_alg_autoload(const char *name) -{ - request_module("%s", name); -} - -struct crypto_alg *crypto_alg_mod_lookup(const char *name) -{ - struct crypto_alg *alg = crypto_alg_lookup(name); - if (alg == NULL) { - crypto_alg_autoload(name); - alg = crypto_alg_lookup(name); - } - return alg; -} diff --git a/crypto/internal.h b/crypto/internal.h index 10880d149afe..8ba30b772ee3 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -48,15 +49,12 @@ static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) struct crypto_alg *crypto_alg_lookup(const char *name); -#ifdef CONFIG_KMOD -void crypto_alg_autoload(const char *name); -struct crypto_alg *crypto_alg_mod_lookup(const char *name); -#else +/* A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. */ static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) { - return crypto_alg_lookup(name); + return try_then_request_module(crypto_alg_lookup(name), name); } -#endif #ifdef CONFIG_CRYPTO_HMAC int crypto_alloc_hmac_block(struct crypto_tfm *tfm); diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 7fa02a737518..8412faeea0f7 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -29,7 +29,7 @@ extern int request_module(const char * name, ...) __attribute__ ((format (printf static inline int request_module(const char * name, ...) { return -ENOSYS; } #endif -#define try_then_request_module(x, mod...) ((x) ?: request_module(mod), (x)) +#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); #ifdef CONFIG_HOTPLUG -- cgit v1.2.3 From cc81ac77f859add27893518bb3151c9df9715f1d Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Thu, 4 Sep 2003 12:39:02 -0700 Subject: [ATM]: pvc/svc missing .owner for proto_ops/family (from levon@movementarian.org) --- net/atm/pvc.c | 2 ++ net/atm/svc.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 9dee7f22c801..c0ce4d4d20b6 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -104,6 +104,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, static struct proto_ops pvc_proto_ops = { .family = PF_ATMPVC, + .owner = THIS_MODULE, .release = vcc_release, .bind = pvc_bind, @@ -134,6 +135,7 @@ static int pvc_create(struct socket *sock,int protocol) static struct net_proto_family pvc_family_ops = { .family = PF_ATMPVC, .create = pvc_create, + .owner = THIS_MODULE, }; diff --git a/net/atm/svc.c b/net/atm/svc.c index 07c0849b37c7..aa46d6ae96d5 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -513,6 +513,7 @@ out: static struct proto_ops svc_proto_ops = { .family = PF_ATMSVC, + .owner = THIS_MODULE, .release = svc_release, .bind = svc_bind, @@ -549,6 +550,7 @@ static int svc_create(struct socket *sock,int protocol) static struct net_proto_family svc_family_ops = { .family = PF_ATMSVC, .create = svc_create, + .owner = THIS_MODULE, }; -- cgit v1.2.3 From a203da9570194d9ecc73ba096acfa33c5e99aa67 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Thu, 4 Sep 2003 12:40:36 -0700 Subject: [ATM]: fix atm_dev module refcount bug (from levon@movementarian.org) --- net/atm/common.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 6fde6b018418..72080c62e535 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -422,26 +422,31 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, int vpi, } if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); - if (error) { - vcc_remove_socket(vcc->sk); - return error; - } + if (error) + goto fail; DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal); DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); - if (!try_module_get(dev->ops->owner)) - return -ENODEV; + if (!try_module_get(dev->ops->owner)) { + error = -ENODEV; + goto fail; + } + if (dev->ops->open) { - error = dev->ops->open(vcc,vpi,vci); - if (error) { - module_put(dev->ops->owner); - vcc_remove_socket(vcc->sk); - return error; - } + if ((error = dev->ops->open(vcc,vpi,vci))) + goto put_module_fail; } return 0; + +put_module_fail: + module_put(dev->ops->owner); +fail: + vcc_remove_socket(vcc->sk); + /* ensure we get dev module ref count correct */ + vcc->dev = NULL; + return error; } -- cgit v1.2.3 From 7d464ed4c51b7a4f9b0ef292dee22c73950a7332 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Thu, 4 Sep 2003 12:41:05 -0700 Subject: [ATM]: reduce CONFIG_PROC_FS #ifdef clutter in .c code (from levon@movementarian.org) --- net/atm/common.c | 4 ---- net/atm/common.h | 13 +++++++++++++ net/atm/proc.c | 7 +++++++ net/atm/resources.c | 28 +++++++++++----------------- net/atm/resources.h | 14 +++++++++++++- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 72080c62e535..62c8f0a72179 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -1114,12 +1114,10 @@ static int __init atm_init(void) printk(KERN_ERR "atmsvc_init() failed with %d\n", error); goto failure; } -#ifdef CONFIG_PROC_FS if ((error = atm_proc_init()) < 0) { printk(KERN_ERR "atm_proc_init() failed with %d\n",error); goto failure; } -#endif return 0; failure: @@ -1130,9 +1128,7 @@ failure: static void __exit atm_exit(void) { -#ifdef CONFIG_PROC_FS atm_proc_exit(); -#endif atmsvc_exit(); atmpvc_exit(); } diff --git a/net/atm/common.h b/net/atm/common.h index eb98c9357431..426f1fa8bbb1 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -33,8 +33,21 @@ int atmpvc_init(void); void atmpvc_exit(void); int atmsvc_init(void); void atmsvc_exit(void); + +#ifdef CONFIG_PROC_FS int atm_proc_init(void); void atm_proc_exit(void); +#else +static inline int atm_proc_init(void) +{ + return 0; +} + +static inline void atm_proc_exit(void) +{ + /* nothing */ +} +#endif /* CONFIG_PROC_FS */ /* SVC */ diff --git a/net/atm/proc.c b/net/atm/proc.c index 05c41491b431..d493ab2cd420 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -593,6 +593,10 @@ int atm_proc_dev_register(struct atm_dev *dev) int digits,num; int error; + /* No proc info */ + if (!dev->ops->proc_read) + return 0; + error = -ENOMEM; digits = 0; for (num = dev->number; num; num /= 10) digits++; @@ -619,6 +623,9 @@ fail1: void atm_proc_dev_deregister(struct atm_dev *dev) { + if (!dev->ops->proc_read) + return; + remove_proc_entry(dev->proc_name, atm_proc_root); kfree(dev->proc_name); } diff --git a/net/atm/resources.c b/net/atm/resources.c index ae3009c6eb4f..bd32c0caabe4 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -110,20 +110,16 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, list_add_tail(&dev->dev_list, &atm_devs); spin_unlock(&atm_dev_lock); -#ifdef CONFIG_PROC_FS - if (ops->proc_read) { - if (atm_proc_dev_register(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_proc_dev_register failed for dev %s\n", - type); - spin_lock(&atm_dev_lock); - list_del(&dev->dev_list); - spin_unlock(&atm_dev_lock); - __free_atm_dev(dev); - return NULL; - } + if (atm_proc_dev_register(dev) < 0) { + printk(KERN_ERR "atm_dev_register: " + "atm_proc_dev_register failed for dev %s\n", + type); + spin_lock(&atm_dev_lock); + list_del(&dev->dev_list); + spin_unlock(&atm_dev_lock); + __free_atm_dev(dev); + return NULL; } -#endif return dev; } @@ -133,10 +129,8 @@ void atm_dev_deregister(struct atm_dev *dev) { unsigned long warning_time; -#ifdef CONFIG_PROC_FS - if (dev->ops->proc_read) - atm_proc_dev_deregister(dev); -#endif + atm_proc_dev_deregister(dev); + spin_lock(&atm_dev_lock); list_del(&dev->dev_list); spin_unlock(&atm_dev_lock); diff --git a/net/atm/resources.h b/net/atm/resources.h index c4ecc1be6a26..1b6bad8db9cc 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -24,6 +24,18 @@ int atm_dev_ioctl(unsigned int cmd, unsigned long arg); int atm_proc_dev_register(struct atm_dev *dev); void atm_proc_dev_deregister(struct atm_dev *dev); -#endif +#else + +static inline int atm_proc_dev_register(struct atm_dev *dev) +{ + return 0; +} + +static inline void atm_proc_dev_deregister(struct atm_dev *dev) +{ + /* nothing */ +} + +#endif /* CONFIG_PROC_FS */ #endif -- cgit v1.2.3 From fd83361256a26645723606655eed8a9df8e49aa6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 4 Sep 2003 12:50:17 -0700 Subject: [NET]: COSA driver fixes. * get rid of leftover sti * no longer need MOD_INC/DEC stuff * get rid of dead code related to MOD_INC/DEC * use module_init/module_exit to cleanly run init code --- drivers/net/wan/cosa.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index d445e916a18b..8a440eea9c60 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -357,11 +357,7 @@ static void debug_status_out(struct cosa_data *cosa, int status); /* ---------- Initialization stuff ---------- */ -#ifdef MODULE -int init_module(void) -#else static int __init cosa_init(void) -#endif { int i; @@ -398,9 +394,9 @@ static int __init cosa_init(void) } return 0; } +module_init(cosa_init); -#ifdef MODULE -void cleanup_module (void) +static void __exit cosa_exit(void) { struct cosa_data *cosa; int i; @@ -424,7 +420,7 @@ void cleanup_module (void) } unregister_chrdev(cosa_major, "cosa"); } -#endif +module_exit(cosa_exit); /* * This function should register all the net devices needed for the @@ -513,7 +509,6 @@ static int cosa_probe(int base, int irq, int dma) if (irq < 0) { unsigned long irqs; /* printk(KERN_INFO "IRQ autoprobe\n"); */ - sti(); irqs = probe_irq_on(); /* * Enable interrupt on tx buffer empty (it sure is) @@ -624,6 +619,7 @@ static void sppp_channel_init(struct channel_data *chan) if (register_netdev(d) == -1) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(chan->pppdev.dev); + free_netdev(chan->pppdev.dev); return; } } @@ -658,7 +654,6 @@ static int cosa_sppp_open(struct net_device *d) chan->rx_done = sppp_rx_done; chan->usage=-1; chan->cosa->usage++; - MOD_INC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); err = sppp_open(d); @@ -666,7 +661,6 @@ static int cosa_sppp_open(struct net_device *d) spin_lock_irqsave(&chan->cosa->lock, flags); chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return err; @@ -726,7 +720,6 @@ static int cosa_sppp_close(struct net_device *d) } chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return 0; } @@ -1187,21 +1180,6 @@ static int cosa_ioctl_common(struct cosa_data *cosa, return cosa_gettype(cosa, (char *)arg); case COSAIORIDSTR: return cosa_getidstr(cosa, (char *)arg); -/* - * These two are _very_ugly_hack_(tm). Don't even look at this. - * Implementing this saved me few reboots after some process segfaulted - * inside this module. - */ -#ifdef MODULE -#if 0 - case COSAIOMINC: - MOD_INC_USE_COUNT; - return 0; - case COSAIOMDEC: - MOD_DEC_USE_COUNT; - return 0; -#endif -#endif case COSAIONRCARDS: return nr_cards; case COSAIONRCHANS: -- cgit v1.2.3 From 7810e97c865383c64b3e76b7666816ea42db6300 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Sep 2003 12:52:21 -0700 Subject: [NET]: Do not ifdef declarations in Space.c --- drivers/net/Space.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1963e60de0b2..be24e20a5cb1 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -97,15 +97,9 @@ extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); -#ifdef CONFIG_SDLA extern struct net_device *sdla_init(void); -#endif -#ifdef CONFIG_COPS extern struct net_device *cops_probe(int unit); -#endif -#ifdef CONFIG_LTPC extern struct net_device *ltpc_probe(void); -#endif /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); -- cgit v1.2.3 From f3e971e437d0cd524eab7c3e00701f6ef6881123 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 4 Sep 2003 12:52:58 -0700 Subject: [NET]: More SDLS fixes. Since sdla.c now has locking instead of cli/sti, it shouldn't be completely busted on SMP. Also, the frad interface registration needed to be done once (and check the result), and undone on module unload. --- drivers/net/wan/Kconfig | 2 +- drivers/net/wan/sdla.c | 36 +++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 49e75710594c..df80c5c25e37 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -465,7 +465,7 @@ config DLCI_MAX config SDLA tristate "SDLA (Sangoma S502/S508) support" - depends on DLCI && ISA && BROKEN_ON_SMP + depends on DLCI && ISA help Say Y here if you need a driver for the Sangoma S502A, S502E, and S508 Frame Relay Access Devices. These are multi-protocol cards, but diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index c91e59da2ed9..e11984b2bb03 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -1633,12 +1633,26 @@ static void setup_sdla(struct net_device *dev) dev->mtu = SDLA_MAX_MTU; } +static int frad_registered; + struct net_device * __init sdla_init(void) { struct net_device *dev; struct frad_local *flp; int err = -ENOMEM; + if (!frad_registered) { + err = register_frad(devname); + if (err) { + printk(KERN_ERR "%s: frad registration failed %d\n", + devname, err); + return ERR_PTR(err); + } + frad_registered = 1; + printk("%s.\n", version); + } + + dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); if (!dev) goto out; @@ -1677,39 +1691,35 @@ out: return ERR_PTR(err); } -int __init sdla_c_setup(void) -{ - printk("%s.\n", version); - register_frad(devname); - return 0; -} - #ifdef MODULE static struct net_device *sdla0; -#endif /* MODULE */ static int __init init_sdla(void) { int result = 0; - sdla_c_setup(); -#ifdef MODULE sdla0 = sdla_init(); if (IS_ERR(sdla0)) result = PTR_ERR(sdla0); -#endif + return result; } static void __exit exit_sdla(void) { -#ifdef MODULE + struct frad_local *flp; + unregister_netdev(sdla0); if (sdla0->irq) free_irq(sdla0->irq, sdla0); + + flp = sdla0->priv; + del_timer_sync(&flp->timer); free_netdev(sdla0); -#endif + + unregister_frad(devname); } +#endif MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 609db23a1f095bfadf1d7a7d162f3e4ef7c222c7 Mon Sep 17 00:00:00 2001 From: John Levon Date: Thu, 4 Sep 2003 13:02:57 -0700 Subject: [ATM]: Remove bogus UNUSED macro usage in pppoatm.c --- net/atm/pppoatm.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index cca22da87ae6..4a8f73b41edf 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -341,16 +341,13 @@ static int pppoatm_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* the following avoids some spurious warnings from the compiler */ -#define UNUSED __attribute__((unused)) - -static int __init UNUSED pppoatm_init(void) +static int __init pppoatm_init(void) { pppoatm_ioctl_set(pppoatm_ioctl); return 0; } -static void __exit UNUSED pppoatm_exit(void) +static void __exit pppoatm_exit(void) { pppoatm_ioctl_set(NULL); } -- cgit v1.2.3 From 616f6f9f9459e0a33a72f61a7b91af9fb0e948cd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Sep 2003 13:19:32 -0700 Subject: [NET]: Remove all the silly 'NET4.x' init messages. --- net/appletalk/ddp.c | 5 +---- net/ax25/af_ax25.c | 3 --- net/bridge/br.c | 2 -- net/ipv4/af_inet.c | 2 -- net/ipv6/af_inet6.c | 2 -- net/ipx/af_ipx.c | 5 ----- net/lapb/lapb_iface.c | 3 --- net/llc/af_llc.c | 5 ----- net/llc/llc_main.c | 2 +- net/unix/af_unix.c | 3 --- 10 files changed, 2 insertions(+), 30 deletions(-) diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 4d5469bd8140..217244bd611d 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1888,8 +1888,6 @@ EXPORT_SYMBOL(aarp_send_ddp); EXPORT_SYMBOL(atrtr_get_dev); EXPORT_SYMBOL(atalk_find_dev_addr); -static char atalk_banner[] __initdata = - KERN_INFO "NET4: AppleTalk 0.20 for Linux NET4.0\n"; static char atalk_err_snap[] __initdata = KERN_CRIT "Unable to register DDP with SNAP.\n"; @@ -1908,7 +1906,6 @@ static int __init atalk_init(void) aarp_proto_init(); atalk_proc_init(); atalk_register_sysctl(); - printk(atalk_banner); return 0; } module_init(atalk_init); @@ -1939,5 +1936,5 @@ module_exit(atalk_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alan Cox "); -MODULE_DESCRIPTION("AppleTalk 0.20 for Linux NET4.0\n"); +MODULE_DESCRIPTION("AppleTalk 0.20\n"); MODULE_ALIAS_NETPROTO(PF_APPLETALK); diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 4bb3798a2638..43662ed9a619 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -2003,8 +2003,6 @@ EXPORT_SYMBOL(asc2ax); EXPORT_SYMBOL(null_ax25_address); EXPORT_SYMBOL(ax25_display_timer); -static char banner[] __initdata = KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n"; - static int __init ax25_init(void) { sock_register(&ax25_family_ops); @@ -2016,7 +2014,6 @@ static int __init ax25_init(void) proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops); proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops); - printk(banner); return 0; } module_init(ax25_init); diff --git a/net/bridge/br.c b/net/bridge/br.c index bf41aa2c61dd..3d90a9017bfc 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -32,8 +32,6 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; static int __init br_init(void) { - printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); - #if defined(CONFIG_INET) && defined(CONFIG_NETFILTER) if (br_netfilter_init()) return 1; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8a5dbadd51f3..3879dca72b92 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1097,8 +1097,6 @@ static int __init inet_init(void) struct inet_protosw *q; struct list_head *r; - printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n"); - if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -EINVAL; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e55d83a6f14d..df60b4030a44 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -723,8 +723,6 @@ static int __init inet6_init(void) #endif #endif - printk(KERN_INFO "IPv6 v0.8 for NET4.0\n"); - if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet6_proto_init: size fault\n"); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 083155a233a6..8c9091ede27d 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1940,10 +1940,6 @@ extern void destroy_8023_client(struct datalink_proto *); static unsigned char ipx_8022_type = 0xE0; static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char ipx_banner[] __initdata = - KERN_INFO "NET4: Linux IPX 0.51 for NET4.0\n" - KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \ - KERN_INFO "IPX Portions Copyright (c) 2000-2003 Conectiva, Inc.\n"; static char ipx_EII_err_msg[] __initdata = KERN_CRIT "IPX: Unable to register with Ethernet II\n"; static char ipx_8023_err_msg[] __initdata = @@ -1980,7 +1976,6 @@ static int __init ipx_init(void) register_netdevice_notifier(&ipx_dev_notifier); ipx_register_sysctl(); ipx_proc_init(); - printk(ipx_banner); return 0; } diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index fbb552adc243..fc71309e7e9b 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -435,11 +435,8 @@ EXPORT_SYMBOL(lapb_disconnect_request); EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -static char banner[] __initdata = KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n"; - static int __init lapb_init(void) { - printk(banner); return 0; } diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 5b011b872d94..ff2710542e4b 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1042,15 +1042,10 @@ static struct proto_ops llc_ui_ops = { .sendpage = sock_no_sendpage, }; -static char llc_ui_banner[] __initdata = - KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, " - "Arnaldo C. Melo, 2002-2003\n"; - int __init llc_ui_init(void) { llc_ui_sap_last_autoport = LLC_SAP_DYN_START; sock_register(&llc_ui_family_ops); - printk(llc_ui_banner); return 0; } diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c index 3ee7b0aa16ae..8f2fc4d7ec71 100644 --- a/net/llc/llc_main.c +++ b/net/llc/llc_main.c @@ -603,5 +603,5 @@ module_exit(llc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001-2003"); -MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); +MODULE_DESCRIPTION("LLC 2.0, IEEE 802.2 extended support"); MODULE_ALIAS_NETPROTO(PF_LLC); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1a3873145535..549c7e303144 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1976,13 +1976,10 @@ static inline void unix_sysctl_register(void) {} static inline void unix_sysctl_unregister(void) {} #endif -static char banner[] __initdata = KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n"; - static int __init af_unix_init(void) { struct sk_buff *dummy_skb; - printk(banner); if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -1; -- cgit v1.2.3 From 977336cca00f794b7cb2f884e9970d1f1dbdbddd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Sep 2003 13:35:02 -0700 Subject: [NET]: Print a KERN_INFO msg when protocol families are {un,}registered. --- net/socket.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/socket.c b/net/socket.c index 74fd11fdd7a8..f0a1a3da7500 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1894,6 +1894,8 @@ int sock_register(struct net_proto_family *ops) err = 0; } net_family_write_unlock(); + printk(KERN_INFO "NET: Registered protocol family %d\n", + ops->family); return err; } @@ -1911,6 +1913,8 @@ int sock_unregister(int family) net_family_write_lock(); net_families[family]=NULL; net_family_write_unlock(); + printk(KERN_INFO "NET: Unregistered protocol family %d\n", + family); return 0; } -- cgit v1.2.3 From c81eb7f2446ad21be044121f2b7a500a7c506526 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Sep 2003 13:40:24 -0700 Subject: [NET]: Kill more verbose init msgs and unused RTNL_DEBUG define. --- include/linux/rtnetlink.h | 3 --- net/core/dv.c | 1 - net/core/rtnetlink.c | 3 --- net/ipv4/ipmr.c | 1 - 4 files changed, 8 deletions(-) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3e3a26916a12..fd8b35209ccc 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -3,9 +3,6 @@ #include -#define RTNL_DEBUG 1 - - /**** * Routing/neighbour discovery messages. ****/ diff --git a/net/core/dv.c b/net/core/dv.c index 62352d7c9bcc..e7de41f94f9c 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -40,7 +40,6 @@ const char sysctl_divert_version[32]="0.46"; /* Current version */ static int __init dv_init(void) { - printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version); return 0; } module_init(dv_init); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4215e4a7dcd0..444f07e51e27 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -559,9 +559,6 @@ struct notifier_block rtnetlink_dev_notifier = { void __init rtnetlink_init(void) { -#ifdef RTNL_DEBUG - printk("Initializing RT netlink socket\n"); -#endif rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv); if (rtnl == NULL) panic("rtnetlink_init: cannot initialize rtnetlink\n"); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 3f671efed9e6..9f5a0485e0a7 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1744,7 +1744,6 @@ static struct inet_protocol pim_protocol = { void __init ip_mr_init(void) { - printk(KERN_INFO "Linux IP multicast router 0.06 plus PIM-SM\n"); mrt_cachep = kmem_cache_create("ip_mrt_cache", sizeof(struct mfc_cache), 0, SLAB_HWCACHE_ALIGN, -- cgit v1.2.3 From cadf0417e85b74d296178c7d158ef20716b82b63 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 4 Sep 2003 17:13:17 -0700 Subject: [PATCH] fix IO hangs The "insert_here" list pointer logic was broken, and unnecessary. Kill it and its associated logic off completely - just tell the IO scheduler what kind of insert it is. This also makes the *_insert_request strategies much easier to follow, imo. --- drivers/block/as-iosched.c | 55 ++++++++++++------------------ drivers/block/deadline-iosched.c | 73 +++++++++++++++------------------------- drivers/block/elevator.c | 26 ++++++-------- drivers/block/ll_rw_blk.c | 32 +++++++----------- drivers/block/noop-iosched.c | 19 ++++++----- drivers/block/scsi_ioctl.c | 2 +- drivers/ide/ide-io.c | 6 ++-- include/linux/blkdev.h | 2 +- include/linux/elevator.h | 16 +++++---- 9 files changed, 100 insertions(+), 131 deletions(-) diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 27384d27b566..3d9c58788373 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -255,7 +255,7 @@ static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq) { as_del_arq_hash(arq); - if (q->last_merge == &arq->request->queuelist) + if (q->last_merge == arq->request) q->last_merge = NULL; } @@ -1347,50 +1347,39 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) } static void -as_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +as_insert_request(request_queue_t *q, struct request *rq, int where) { struct as_data *ad = q->elevator.elevator_data; struct as_rq *arq = RQ_DATA(rq); - if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) { - q->last_merge = NULL; - - if (insert_here != ad->dispatch) { + switch (where) { + case ELEVATOR_INSERT_BACK: while (ad->next_arq[REQ_SYNC]) as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); while (ad->next_arq[REQ_ASYNC]) as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); - } - - if (!insert_here) - insert_here = ad->dispatch->prev; - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = ad->dispatch; - } - - if (insert_here) { - list_add(&rq->queuelist, insert_here); - - /* Stop anticipating - let this request get through */ - if (list_empty(ad->dispatch)) + list_add_tail(&rq->queuelist, ad->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, ad->dispatch); as_antic_stop(ad); - - return; + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + as_add_request(ad, arq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { as_add_arq_hash(ad, arq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - as_add_request(ad, arq); } /* @@ -1438,7 +1427,7 @@ as_latter_request(request_queue_t *q, struct request *rq) } static int -as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +as_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct as_data *ad = q->elevator.elevator_data; sector_t rb_key = bio->bi_sector + bio_sectors(bio); @@ -1450,7 +1439,7 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -1482,11 +1471,11 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) as_hot_arq_hash(ad, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -1514,7 +1503,7 @@ static void as_merged_request(request_queue_t *q, struct request *req) */ } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index dc2b121a9239..8bb37f65d536 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c @@ -33,13 +33,7 @@ static const int deadline_hash_shift = 5; #define DL_HASH_ENTRIES (1 << deadline_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) #define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->hash_valid_count - -#define DL_INVALIDATE_HASH(dd) \ - do { \ - if (!++(dd)->hash_valid_count) \ - (dd)->hash_valid_count = 1; \ - } while (0) +#define ON_HASH(drq) (drq)->on_hash struct deadline_data { /* @@ -58,7 +52,6 @@ struct deadline_data { struct deadline_rq *next_drq[2]; struct list_head *dispatch; /* driver dispatch queue */ struct list_head *hash; /* request hash */ - unsigned long hash_valid_count; /* barrier hash count */ unsigned int batching; /* number of sequential requests made */ sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ @@ -90,7 +83,7 @@ struct deadline_rq { * request hash, key is the ending offset (for back merge lookup) */ struct list_head hash; - unsigned long hash_valid_count; + char on_hash; /* * expire fifo @@ -110,7 +103,7 @@ static kmem_cache_t *drq_pool; */ static inline void __deadline_del_drq_hash(struct deadline_rq *drq) { - drq->hash_valid_count = 0; + drq->on_hash = 0; list_del_init(&drq->hash); } @@ -125,7 +118,7 @@ deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq) { deadline_del_drq_hash(drq); - if (q->last_merge == &drq->request->queuelist) + if (q->last_merge == drq->request) q->last_merge = NULL; } @@ -136,7 +129,7 @@ deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) BUG_ON(ON_HASH(drq)); - drq->hash_valid_count = dd->hash_valid_count; + drq->on_hash = 1; list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } @@ -169,8 +162,7 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) BUG_ON(!ON_HASH(drq)); - if (!rq_mergeable(__rq) - || drq->hash_valid_count != dd->hash_valid_count) { + if (!rq_mergeable(__rq)) { __deadline_del_drq_hash(drq); continue; } @@ -324,7 +316,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq) } static int -deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct deadline_data *dd = q->elevator.elevator_data; struct request *__rq; @@ -335,7 +327,7 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -371,11 +363,11 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) deadline_hot_drq_hash(dd, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -398,7 +390,7 @@ static void deadline_merged_request(request_queue_t *q, struct request *req) deadline_add_drq_rb(dd, drq); } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void @@ -621,43 +613,35 @@ dispatch: } static void -deadline_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +deadline_insert_request(request_queue_t *q, struct request *rq, int where) { struct deadline_data *dd = q->elevator.elevator_data; struct deadline_rq *drq = RQ_DATA(rq); - if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) { - DL_INVALIDATE_HASH(dd); - q->last_merge = NULL; - - if (insert_here != dd->dispatch) { + switch (where) { + case ELEVATOR_INSERT_BACK: while (deadline_dispatch_requests(dd)) ; - } - - if (!insert_here) - insert_here = dd->dispatch->prev; - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = dd->dispatch; - } - - if (insert_here) { - list_add(&rq->queuelist, insert_here); - return; + list_add_tail(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + deadline_add_request(dd, drq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { deadline_add_drq_hash(dd, drq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - deadline_add_request(dd, drq); } static int deadline_queue_empty(request_queue_t *q) @@ -748,7 +732,6 @@ static int deadline_init(request_queue_t *q, elevator_t *e) dd->dispatch = &q->queue_head; dd->fifo_expire[READ] = read_expire; dd->fifo_expire[WRITE] = write_expire; - dd->hash_valid_count = 1; dd->writes_starved = writes_starved; dd->front_merges = 1; dd->fifo_batch = fifo_batch; @@ -779,7 +762,7 @@ deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) drq->request = rq; INIT_LIST_HEAD(&drq->hash); - drq->hash_valid_count = 0; + drq->on_hash = 0; INIT_LIST_HEAD(&drq->fifo); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 4654fddecd7d..fcb00cfa4fd7 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -81,7 +81,7 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio) inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) { if (q->last_merge) - return elv_try_merge(list_entry_rq(q->last_merge), bio); + return elv_try_merge(q->last_merge, bio); return ELEVATOR_NO_MERGE; } @@ -117,12 +117,12 @@ int elevator_global_init(void) return 0; } -int elv_merge(request_queue_t *q, struct list_head **entry, struct bio *bio) +int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) { elevator_t *e = &q->elevator; if (e->elevator_merge_fn) - return e->elevator_merge_fn(q, entry, bio); + return e->elevator_merge_fn(q, req, bio); return ELEVATOR_NO_MERGE; } @@ -140,7 +140,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, { elevator_t *e = &q->elevator; - if (q->last_merge == &next->queuelist) + if (q->last_merge == next) q->last_merge = NULL; if (e->elevator_merge_req_fn) @@ -156,29 +156,25 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) if (q->elevator.elevator_requeue_req_fn) q->elevator.elevator_requeue_req_fn(q, rq); else - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } -void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { - struct list_head *insert = NULL; - - if (!at_end) - insert = &q->queue_head; if (plug) blk_plug_device(q); - q->elevator.elevator_add_req_fn(q, rq, insert); + q->elevator.elevator_add_req_fn(q, rq, where); } -void elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, at_end, plug); + __elv_add_request(q, rq, where, plug); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -200,7 +196,7 @@ struct request *elv_next_request(request_queue_t *q) */ rq->flags |= REQ_STARTED; - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) @@ -238,7 +234,7 @@ void elv_remove_request(request_queue_t *q, struct request *rq) * deleted without ever being given to driver (merged with another * request). */ - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if (e->elevator_remove_req_fn) diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index c57d8d0f42c2..541b45c519ef 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -703,7 +703,7 @@ void blk_queue_invalidate_tags(request_queue_t *q) blk_queue_end_tag(q, rq); rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); } } @@ -1632,11 +1632,16 @@ void blk_insert_request(request_queue_t *q, struct request *rq, if(reinsert) { blk_requeue_request(q, rq); } else { + int where = ELEVATOR_INSERT_BACK; + + if (at_head) + where = ELEVATOR_INSERT_FRONT; + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); drive_stat_acct(rq, rq->nr_sectors, 1); - __elv_add_request(q, rq, !at_head, 0); + __elv_add_request(q, rq, where, 0); } q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1669,8 +1674,7 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) * queue lock is held and interrupts disabled, as we muck with the * request queue list. */ -static inline void add_request(request_queue_t * q, struct request * req, - struct list_head *insert_here) +static inline void add_request(request_queue_t * q, struct request * req) { drive_stat_acct(req, req->nr_sectors, 1); @@ -1681,7 +1685,7 @@ static inline void add_request(request_queue_t * q, struct request * req, * elevator indicated where it wants this request to be * inserted at elevator_merge time */ - __elv_add_request_pos(q, req, insert_here); + __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } /* @@ -1880,7 +1884,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; - struct list_head *insert_here; sector_t sector; sector = bio->bi_sector; @@ -1903,7 +1906,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) ra = bio->bi_rw & (1 << BIO_RW_AHEAD); again: - insert_here = NULL; spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) { @@ -1913,17 +1915,13 @@ again: if (barrier) goto get_rq; - el_ret = elv_merge(q, &insert_here, bio); + el_ret = elv_merge(q, &req, bio); switch (el_ret) { case ELEVATOR_BACK_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->back_merge_fn(q, req, bio)) { - insert_here = &req->queuelist; + if (!q->back_merge_fn(q, req, bio)) break; - } req->biotail->bi_next = bio; req->biotail = bio; @@ -1934,14 +1932,10 @@ again: goto out; case ELEVATOR_FRONT_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->front_merge_fn(q, req, bio)) { - insert_here = req->queuelist.prev; + if (!q->front_merge_fn(q, req, bio)) break; - } bio->bi_next = req->bio; req->cbio = req->bio = bio; @@ -2029,7 +2023,7 @@ get_rq: req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; - add_request(q, req, insert_here); + add_request(q, req); out: if (freereq) __blk_put_request(q, freereq); diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c index 2eadd041914b..7511b955de70 100644 --- a/drivers/block/noop-iosched.c +++ b/drivers/block/noop-iosched.c @@ -17,17 +17,15 @@ /* * See if we can find a request that this buffer can be coalesced with. */ -int elevator_noop_merge(request_queue_t *q, struct list_head **insert, +int elevator_noop_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct list_head *entry = &q->queue_head; struct request *__rq; int ret; - if ((ret = elv_try_last_merge(q, bio))) { - *insert = q->last_merge; + if ((ret = elv_try_last_merge(q, bio))) return ret; - } while ((entry = entry->prev) != &q->queue_head) { __rq = list_entry_rq(entry); @@ -41,8 +39,8 @@ int elevator_noop_merge(request_queue_t *q, struct list_head **insert, continue; if ((ret = elv_try_merge(__rq, bio))) { - *insert = &__rq->queuelist; - q->last_merge = &__rq->queuelist; + *req = __rq; + q->last_merge = __rq; return ret; } } @@ -57,8 +55,13 @@ void elevator_noop_merge_requests(request_queue_t *q, struct request *req, } void elevator_noop_add_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) + int where) { + struct list_head *insert = q->queue_head.prev; + + if (where == ELEVATOR_INSERT_FRONT) + insert = &q->queue_head; + list_add_tail(&rq->queuelist, &q->queue_head); /* @@ -67,7 +70,7 @@ void elevator_noop_add_request(request_queue_t *q, struct request *rq, if (rq->flags & REQ_HARDBARRIER) q->last_merge = NULL; else if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } struct request *elevator_noop_next_request(request_queue_t *q) diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 94574b14f30b..3d18a7a70108 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -68,7 +68,7 @@ static int blk_do_rq(request_queue_t *q, struct block_device *bdev, rq->flags |= REQ_NOMERGE; rq->waiting = &wait; - elv_add_request(q, rq, 1, 1); + elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(&wait); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 2b94c9450336..0d9fff1f883d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1387,7 +1387,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); DECLARE_COMPLETION(wait); - int insert_end = 1, err; + int where = ELEVATOR_INSERT_BACK, err; int must_wait = (action == ide_wait || action == ide_head_wait); #ifdef CONFIG_BLK_DEV_PDC4030 @@ -1419,10 +1419,10 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio spin_lock_irqsave(&ide_lock, flags); if (action == ide_preempt || action == ide_head_wait) { hwgroup->rq = NULL; - insert_end = 0; + where = ELEVATOR_INSERT_FRONT; rq->flags |= REQ_PREEMPT; } - __elv_add_request(drive->queue, rq, insert_end, 0); + __elv_add_request(drive->queue, rq, where, 0); ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9c7e6d86e810..285fd86e2b48 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -270,7 +270,7 @@ struct request_queue * Together with queue_head for cacheline sharing */ struct list_head queue_head; - struct list_head *last_merge; + struct request *last_merge; elevator_t elevator; /* diff --git a/include/linux/elevator.h b/include/linux/elevator.h index ac30ae089069..e43d670c1371 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -1,7 +1,7 @@ #ifndef _LINUX_ELEVATOR_H #define _LINUX_ELEVATOR_H -typedef int (elevator_merge_fn) (request_queue_t *, struct list_head **, +typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct bio *); typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); @@ -10,7 +10,7 @@ typedef void (elevator_merged_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_next_req_fn) (request_queue_t *); -typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *); +typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, int); typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); @@ -62,7 +62,7 @@ struct elevator_s */ extern void elv_add_request(request_queue_t *, struct request *, int, int); extern void __elv_add_request(request_queue_t *, struct request *, int, int); -extern int elv_merge(request_queue_t *, struct list_head **, struct bio *); +extern int elv_merge(request_queue_t *, struct request **, struct bio *); extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); extern void elv_merged_request(request_queue_t *, struct request *); @@ -79,9 +79,6 @@ extern void elv_completed_request(request_queue_t *, struct request *); extern int elv_set_request(request_queue_t *, struct request *, int); extern void elv_put_request(request_queue_t *, struct request *); -#define __elv_add_request_pos(q, rq, pos) \ - (q)->elevator.elevator_add_req_fn((q), (rq), (pos)) - /* * noop I/O scheduler. always merges, always inserts new request at tail */ @@ -111,4 +108,11 @@ extern inline int elv_try_last_merge(request_queue_t *, struct bio *); #define ELEVATOR_FRONT_MERGE 1 #define ELEVATOR_BACK_MERGE 2 +/* + * Insertion selection + */ +#define ELEVATOR_INSERT_FRONT 1 +#define ELEVATOR_INSERT_BACK 2 +#define ELEVATOR_INSERT_SORT 3 + #endif -- cgit v1.2.3 From 73790646259cc3e32e60efe27c02e7c7e8fd19ec Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 4 Sep 2003 17:15:28 -0700 Subject: [PATCH] Move MODULE_ALIAS_LDISC to tty_ldisc.h MODULE_ALIAS_LDISC() is not in any way architecture-specific, so don't put it in architecture header files. Here's a patch which moves it to a more sensible location. --- include/asm-i386/termios.h | 2 -- include/asm-sparc/termios.h | 3 --- include/asm-sparc64/termios.h | 3 --- include/linux/tty_ldisc.h | 3 +++ 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/include/asm-i386/termios.h b/include/asm-i386/termios.h index c0fded995489..03f548536d6b 100644 --- a/include/asm-i386/termios.h +++ b/include/asm-i386/termios.h @@ -102,8 +102,6 @@ struct termio { #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) #endif /* __KERNEL__ */ #endif /* _I386_TERMIOS_H */ diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 48ba080c0794..0a8ad4cac125 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -169,9 +169,6 @@ struct winsize { 0; \ }) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) - #endif /* __KERNEL__ */ #endif /* _SPARC_TERMIOS_H */ diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index 4e7fef518a25..8effce0da087 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -168,9 +168,6 @@ struct winsize { 0; \ }) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) - #endif /* __KERNEL__ */ #endif /* _SPARC64_TERMIOS_H */ diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ac8ac46845ba..c851b7dc997e 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -138,4 +138,7 @@ struct tty_ldisc { #define LDISC_FLAG_DEFINED 0x00000001 +#define MODULE_ALIAS_LDISC(ldisc) \ + MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) + #endif /* _LINUX_TTY_LDISC_H */ -- cgit v1.2.3 From b99c26562c4af97cd31ccb0b29c649b4d0816e1a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 4 Sep 2003 17:15:37 -0700 Subject: [PATCH] ide: fix ide_cs oops with TCQ From Matias Alejo Garcia . --- drivers/ide/ide-disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 39693bcc7d0f..8bf402224197 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1689,7 +1689,8 @@ static void idedisk_setup (ide_drive_t *drive) write_cache(drive, (id->cfs_enable_2 & 0x3000)); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - HWIF(drive)->ide_dma_queued_on(drive); + if (drive->using_dma) + HWIF(drive)->ide_dma_queued_on(drive); #endif } -- cgit v1.2.3 From 968f11a8688e1be78719154d05bcab061bbfde2b Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Thu, 4 Sep 2003 18:00:45 -0700 Subject: [PATCH] Unpinned futexes v2: indexing changes This changes the way futexes are indexed, so that they don't pin pages. It also fixes some bugs with private mappings and COW pages. Currently, all futexes look up the page at the userspace address and pin it, using the pair (page,offset) as an index into a table of waiting futexes. Any page with a futex waiting on it remains pinned in RAM, which is a problem when many futexes are used, especially with FUTEX_FD. Another problem is that the page is not always the correct one, if it can be changed later by a COW (copy on write) operation. This can happen when waiting on a futex without writing to it after fork(), exec() or mmap(), if the page is then written to before attempting to wake a futex at the same adress. There are two symptoms of the COW problem: - The wrong process can receive wakeups - A process can fail to receive required wakeups. This patch fixes both by changing the indexing so that VM_SHARED mappings use the triple (inode,offset,index), and private mappings use the pair (mm,virtual_address). The former correctly handles all shared mappings, including tmpfs and therefore all kinds of shared memory (IPC shm, /dev/shm and MAP_ANON|MAP_SHARED). This works because every mapping which is VM_SHARED has an associated non-zero vma->vm_file, and hence inode. (This is ensured in do_mmap_pgoff, where it calls shmem_zero_setup). The latter handles all private mappings, both files and anonymous. It isn't affected by COW, because it doesn't care about the actual pages, just the virtual address. The patch has a few bonuses: 1. It removes the vcache implementation, as only futexes were using it, and they don't any more. 2. Removing the vcache should make COW page faults a bit faster. 3. Futex operations no longer take the page table lock, walk the page table, fault in pages that aren't mapped in the page table, or do a vcache hash lookup - they are mostly a simple offset calculation with one hash for the futex table. So they should be noticably faster. Special thanks to Hugh Dickins, Andrew Morton and Rusty Russell for insightful feedback. All suggestions are included. --- include/linux/mm.h | 1 + include/linux/vcache.h | 26 --- kernel/futex.c | 427 ++++++++++++++++++++++++++----------------------- mm/Makefile | 2 +- mm/fremap.c | 31 +++- mm/memory.c | 2 - mm/vcache.c | 90 ----------- 7 files changed, 249 insertions(+), 330 deletions(-) delete mode 100644 include/linux/vcache.h delete mode 100644 mm/vcache.c diff --git a/include/linux/mm.h b/include/linux/mm.h index 445fc58751c7..9f9743146b54 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -110,6 +110,7 @@ struct vm_area_struct { #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ +#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff --git a/include/linux/vcache.h b/include/linux/vcache.h deleted file mode 100644 index 5708fe6a908a..000000000000 --- a/include/linux/vcache.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * virtual => physical mapping cache support. - */ -#ifndef _LINUX_VCACHE_H -#define _LINUX_VCACHE_H - -typedef struct vcache_s { - unsigned long address; - struct mm_struct *mm; - struct list_head hash_entry; - void (*callback)(struct vcache_s *data, struct page *new_page); -} vcache_t; - -extern spinlock_t vcache_lock; - -extern void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new_page)); - -extern void __detach_vcache(vcache_t *vcache); - -extern void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page); - -#endif diff --git a/kernel/futex.c b/kernel/futex.c index 4557addfc6d6..a4feceee661a 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -5,6 +5,9 @@ * Generalized futexes, futex requeueing, misc fixes by Ingo Molnar * (C) Copyright 2003 Red Hat Inc, All Rights Reserved * + * Removed page pinning, fix privately mapped COW pages and other cleanups + * (C) Copyright 2003 Jamie Lokier + * * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly * enough at me, Linus for the original (flawed) idea, Matthew * Kirkwood for proof-of-concept implementation. @@ -33,11 +36,31 @@ #include #include #include -#include #include +#include #define FUTEX_HASHBITS 8 +/* + * Futexes are matched on equal values of this key. + * The key type depends on whether it's a shared or private mapping. + */ +union futex_key { + struct { + unsigned long pgoff; + struct inode *inode; + } shared; + struct { + unsigned long uaddr; + struct mm_struct *mm; + } private; + struct { + unsigned long word; + void *ptr; + } both; + int offset; +}; + /* * We use this hashed waitqueue instead of a normal wait_queue_t, so * we can wake only the relevant ones (hashed queues may be shared): @@ -46,12 +69,8 @@ struct futex_q { struct list_head list; wait_queue_head_t waiters; - /* Page struct and offset within it. */ - struct page *page; - int offset; - - /* the virtual => physical COW-safe cache */ - vcache_t vcache; + /* Key which the futex is hashed on. */ + union futex_key key; /* For fd, sigio sent using these. */ int fd; @@ -66,111 +85,149 @@ static spinlock_t futex_lock = SPIN_LOCK_UNLOCKED; static struct vfsmount *futex_mnt; /* - * These are all locks that are necessery to look up a physical - * mapping safely, and modify/search the futex hash, atomically: + * We hash on the keys returned from get_futex_key (see below). */ -static inline void lock_futex_mm(void) +static inline struct list_head *hash_futex(union futex_key *key) { - spin_lock(¤t->mm->page_table_lock); - spin_lock(&vcache_lock); - spin_lock(&futex_lock); -} - -static inline void unlock_futex_mm(void) -{ - spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); - spin_unlock(¤t->mm->page_table_lock); + return &futex_queues[hash_long(key->both.word + + (unsigned long) key->both.ptr + + key->offset, FUTEX_HASHBITS)]; } /* - * The physical page is shared, so we can hash on its address: + * Return 1 if two futex_keys are equal, 0 otherwise. */ -static inline struct list_head *hash_futex(struct page *page, int offset) +static inline int match_futex(union futex_key *key1, union futex_key *key2) { - return &futex_queues[hash_long((unsigned long)page + offset, - FUTEX_HASHBITS)]; + return (key1->both.word == key2->both.word + && key1->both.ptr == key2->both.ptr + && key1->offset == key2->offset); } /* - * Get kernel address of the user page and pin it. + * Get parameters which are the keys for a futex. + * + * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode, + * offset_within_page). For private mappings, it's (uaddr, current->mm). + * We can usually work out the index without swapping in the page. * - * Must be called with (and returns with) all futex-MM locks held. + * Returns: 0, or negative error code. + * The key words are stored in *key on success. + * + * Should be called with ¤t->mm->mmap_sem, + * but NOT &futex_lock or ¤t->mm->page_table_lock. */ -static inline struct page *__pin_page_atomic (struct page *page) -{ - if (!PageReserved(page)) - get_page(page); - return page; -} - -static struct page *__pin_page(unsigned long addr) +static int get_futex_key(unsigned long uaddr, union futex_key *key) { struct mm_struct *mm = current->mm; - struct page *page, *tmp; + struct vm_area_struct *vma; + struct page *page; int err; /* - * Do a quick atomic lookup first - this is the fastpath. + * The futex address must be "naturally" aligned. + */ + key->offset = uaddr % PAGE_SIZE; + if (unlikely((key->offset % sizeof(u32)) != 0)) + return -EINVAL; + uaddr -= key->offset; + + /* + * The futex is hashed differently depending on whether + * it's in a shared or private mapping. So check vma first. + */ + vma = find_extend_vma(mm, uaddr); + if (unlikely(!vma)) + return -EFAULT; + + /* + * Permissions. */ - page = follow_page(mm, addr, 0); - if (likely(page != NULL)) - return __pin_page_atomic(page); + if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ)) + return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES; /* - * No luck - need to fault in the page: + * Private mappings are handled in a simple way. + * + * NOTE: When userspace waits on a MAP_SHARED mapping, even if + * it's a read-only handle, it's expected that futexes attach to + * the object not the particular process. Therefore we use + * VM_MAYSHARE here, not VM_SHARED which is restricted to shared + * mappings of _writable_ handles. */ -repeat_lookup: + if (likely(!(vma->vm_flags & VM_MAYSHARE))) { + key->private.mm = mm; + key->private.uaddr = uaddr; + return 0; + } - unlock_futex_mm(); + /* + * Linear mappings are also simple. + */ + key->shared.inode = vma->vm_file->f_dentry->d_inode; + if (likely(!(vma->vm_flags & VM_NONLINEAR))) { + key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff); + return 0; + } - down_read(&mm->mmap_sem); - err = get_user_pages(current, mm, addr, 1, 0, 0, &page, NULL); - up_read(&mm->mmap_sem); + /* + * We could walk the page table to read the non-linear + * pte, and get the page index without fetching the page + * from swap. But that's a lot of code to duplicate here + * for a rare case, so we simply fetch the page. + */ - lock_futex_mm(); + /* + * Do a quick atomic lookup first - this is the fastpath. + */ + spin_lock(¤t->mm->page_table_lock); + page = follow_page(mm, uaddr, 0); + if (likely(page != NULL)) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + spin_unlock(¤t->mm->page_table_lock); + return 0; + } + spin_unlock(¤t->mm->page_table_lock); - if (err < 0) - return NULL; /* - * Since the faulting happened with locks released, we have to - * check for races: + * Do it the general way. */ - tmp = follow_page(mm, addr, 0); - if (tmp != page) { + err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); + if (err >= 0) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); put_page(page); - goto repeat_lookup; } - - return page; + return err; } + /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static inline int futex_wake(unsigned long uaddr, int offset, int num) +static inline int futex_wake(unsigned long uaddr, int num) { struct list_head *i, *next, *head; - struct page *page; - int ret = 0; + union futex_key key; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out; - head = hash_futex(page, offset); + head = hash_futex(&key); + spin_lock(&futex_lock); list_for_each_safe(i, next, head) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page && this->offset == offset) { + if (match_futex (&this->key, &key)) { list_del_init(i); - __detach_vcache(&this->vcache); wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); @@ -179,113 +236,74 @@ static inline int futex_wake(unsigned long uaddr, int offset, int num) break; } } + spin_unlock(&futex_lock); - unlock_futex_mm(); - put_page(page); - +out: + up_read(¤t->mm->mmap_sem); return ret; } -/* - * This gets called by the COW code, we have to rehash any - * futexes that were pending on the old physical page, and - * rehash it to the new physical page. The pagetable_lock - * and vcache_lock is already held: - */ -static void futex_vcache_callback(vcache_t *vcache, struct page *new_page) -{ - struct futex_q *q = container_of(vcache, struct futex_q, vcache); - struct list_head *head = hash_futex(new_page, q->offset); - - spin_lock(&futex_lock); - - if (!list_empty(&q->list)) { - put_page(q->page); - q->page = new_page; - __pin_page_atomic(new_page); - list_del(&q->list); - list_add_tail(&q->list, head); - } - - spin_unlock(&futex_lock); -} - /* * Requeue all waiters hashed on one physical page to another * physical page. */ -static inline int futex_requeue(unsigned long uaddr1, int offset1, - unsigned long uaddr2, int offset2, int nr_wake, int nr_requeue) +static inline int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, + int nr_wake, int nr_requeue) { struct list_head *i, *next, *head1, *head2; - struct page *page1 = NULL, *page2 = NULL; - int ret = 0; + union futex_key key1, key2; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page1 = __pin_page(uaddr1 - offset1); - if (!page1) + ret = get_futex_key(uaddr1, &key1); + if (unlikely(ret != 0)) goto out; - page2 = __pin_page(uaddr2 - offset2); - if (!page2) + ret = get_futex_key(uaddr2, &key2); + if (unlikely(ret != 0)) goto out; - head1 = hash_futex(page1, offset1); - head2 = hash_futex(page2, offset2); + head1 = hash_futex(&key1); + head2 = hash_futex(&key2); + spin_lock(&futex_lock); list_for_each_safe(i, next, head1) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page1 && this->offset == offset1) { + if (match_futex (&this->key, &key1)) { list_del_init(i); - __detach_vcache(&this->vcache); if (++ret <= nr_wake) { wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); } else { - put_page(this->page); - __pin_page_atomic (page2); list_add_tail(i, head2); - __attach_vcache(&this->vcache, uaddr2, - current->mm, futex_vcache_callback); - this->offset = offset2; - this->page = page2; + this->key = key2; if (ret - nr_wake >= nr_requeue) break; } } } + spin_unlock(&futex_lock); out: - unlock_futex_mm(); - - if (page1) - put_page(page1); - if (page2) - put_page(page2); - + up_read(¤t->mm->mmap_sem); return ret; } -static inline void __queue_me(struct futex_q *q, struct page *page, - unsigned long uaddr, int offset, - int fd, struct file *filp) +static inline void queue_me(struct futex_q *q, union futex_key *key, + int fd, struct file *filp) { - struct list_head *head = hash_futex(page, offset); + struct list_head *head = hash_futex(key); - q->offset = offset; + q->key = *key; q->fd = fd; q->filp = filp; - q->page = page; + spin_lock(&futex_lock); list_add_tail(&q->list, head); - /* - * We register a futex callback to this virtual address, - * to make sure a COW properly rehashes the futex-queue. - */ - __attach_vcache(&q->vcache, uaddr, current->mm, futex_vcache_callback); + spin_unlock(&futex_lock); } /* Return 1 if we were still queued (ie. 0 means we were woken) */ @@ -293,83 +311,107 @@ static inline int unqueue_me(struct futex_q *q) { int ret = 0; - spin_lock(&vcache_lock); spin_lock(&futex_lock); if (!list_empty(&q->list)) { list_del(&q->list); - __detach_vcache(&q->vcache); ret = 1; } spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); return ret; } -static inline int futex_wait(unsigned long uaddr, - int offset, - int val, - unsigned long time) +static inline int futex_wait(unsigned long uaddr, int val, unsigned long time) { DECLARE_WAITQUEUE(wait, current); - int ret = 0, curval; - struct page *page; + int ret, curval; + union futex_key key; struct futex_q q; + try_again: init_waitqueue_head(&q.waiters); - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } - __queue_me(&q, page, uaddr, offset, -1, NULL); + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out_release_sem; + + queue_me(&q, &key, -1, NULL); /* - * Page is pinned, but may no longer be in this address space. - * It cannot schedule, so we access it with the spinlock held. + * Access the page after the futex is queued. + * We hold the mmap semaphore, so the mapping cannot have changed + * since we looked it up. */ if (get_user(curval, (int *)uaddr) != 0) { - unlock_futex_mm(); ret = -EFAULT; - goto out; + goto out_unqueue; } if (curval != val) { - unlock_futex_mm(); ret = -EWOULDBLOCK; - goto out; + goto out_unqueue; } + + /* + * Now the futex is queued and we have checked the data, we + * don't want to hold mmap_sem while we sleep. + */ + up_read(¤t->mm->mmap_sem); + /* - * The get_user() above might fault and schedule so we - * cannot just set TASK_INTERRUPTIBLE state when queueing - * ourselves into the futex hash. This code thus has to + * There might have been scheduling since the queue_me(), as we + * cannot hold a spinlock across the get_user() in case it + * faults. So we cannot just set TASK_INTERRUPTIBLE state when + * queueing ourselves into the futex hash. This code thus has to * rely on the futex_wake() code doing a wakeup after removing * the waiter from the list. */ add_wait_queue(&q.waiters, &wait); + spin_lock(&futex_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!list_empty(&q.list)) { - unlock_futex_mm(); - time = schedule_timeout(time); + + if (unlikely(list_empty(&q.list))) { + /* + * We were woken already. + */ + spin_unlock(&futex_lock); + set_current_state(TASK_RUNNING); + return 0; } + + spin_unlock(&futex_lock); + time = schedule_timeout(time); set_current_state(TASK_RUNNING); + /* * NOTE: we don't remove ourselves from the waitqueue because * we are the only user of it. */ - if (time == 0) { - ret = -ETIMEDOUT; - goto out; - } + + /* + * Were we woken or interrupted for a valid reason? + */ + ret = unqueue_me(&q); + if (ret == 0) + return 0; + if (time == 0) + return -ETIMEDOUT; if (signal_pending(current)) - ret = -EINTR; -out: - /* Were we woken up anyway? */ + return -EINTR; + + /* + * No, it was a spurious wakeup. Try again. Should never happen. :) + */ + goto try_again; + + out_unqueue: + /* + * Were we unqueued anyway? + */ if (!unqueue_me(&q)) ret = 0; - put_page(q.page); - + out_release_sem: + up_read(¤t->mm->mmap_sem); return ret; } @@ -378,7 +420,6 @@ static int futex_close(struct inode *inode, struct file *filp) struct futex_q *q = filp->private_data; unqueue_me(q); - put_page(q->page); kfree(filp->private_data); return 0; } @@ -406,12 +447,12 @@ static struct file_operations futex_fops = { /* Signal allows caller to avoid the race which would occur if they set the sigio stuff up afterwards. */ -static int futex_fd(unsigned long uaddr, int offset, int signal) +static int futex_fd(unsigned long uaddr, int signal) { - struct page *page = NULL; struct futex_q *q; + union futex_key key; struct file *filp; - int ret; + int ret, err; ret = -EINVAL; if (signal < 0 || signal > _NSIG) @@ -450,69 +491,47 @@ static int futex_fd(unsigned long uaddr, int offset, int signal) goto out; } - lock_futex_mm(); - - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); + down_read(¤t->mm->mmap_sem); + err = get_futex_key(uaddr, &key); + up_read(¤t->mm->mmap_sem); + if (unlikely(err != 0)) { put_unused_fd(ret); put_filp(filp); kfree(q); - return -EFAULT; + return err; } init_waitqueue_head(&q->waiters); filp->private_data = q; - __queue_me(q, page, uaddr, offset, ret, filp); - - unlock_futex_mm(); + queue_me(q, &key, ret, filp); /* Now we map fd to filp, so userspace can access it */ fd_install(ret, filp); - page = NULL; out: - if (page) - put_page(page); return ret; } long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, unsigned long uaddr2, int val2) { - unsigned long pos_in_page; int ret; - pos_in_page = uaddr % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page % sizeof(u32)) - return -EINVAL; - switch (op) { case FUTEX_WAIT: - ret = futex_wait(uaddr, pos_in_page, val, timeout); + ret = futex_wait(uaddr, val, timeout); break; case FUTEX_WAKE: - ret = futex_wake(uaddr, pos_in_page, val); + ret = futex_wake(uaddr, val); break; case FUTEX_FD: /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ - ret = futex_fd(uaddr, pos_in_page, val); + ret = futex_fd(uaddr, val); break; case FUTEX_REQUEUE: - { - unsigned long pos_in_page2 = uaddr2 % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page2 % sizeof(u32)) - return -EINVAL; - - ret = futex_requeue(uaddr, pos_in_page, uaddr2, pos_in_page2, - val, val2); + ret = futex_requeue(uaddr, uaddr2, val, val2); break; - } default: ret = -ENOSYS; } diff --git a/mm/Makefile b/mm/Makefile index a8de64ff3525..c66aba5886f8 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -9,6 +9,6 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o readahead.o \ - slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y) + slab.o swap.o truncate.o vmscan.o $(mmu-y) obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o diff --git a/mm/fremap.c b/mm/fremap.c index 8f96af82b4e8..b19bdde07bb6 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -144,9 +144,10 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, return err; #endif - down_read(&mm->mmap_sem); - + /* We need down_write() to change vma->vm_flags. */ + down_write(&mm->mmap_sem); vma = find_vma(mm, start); + /* * Make sure the vma is shared, that it supports prefaulting, * and that the remapped range is valid and fully within @@ -155,11 +156,27 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, if (vma && (vma->vm_flags & VM_SHARED) && vma->vm_ops && vma->vm_ops->populate && end > start && start >= vma->vm_start && - end <= vma->vm_end) - err = vma->vm_ops->populate(vma, start, size, vma->vm_page_prot, - pgoff, flags & MAP_NONBLOCK); - - up_read(&mm->mmap_sem); + end <= vma->vm_end) { + + /* Must set VM_NONLINEAR before any pages are populated. */ + if (pgoff != ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff) + vma->vm_flags |= VM_NONLINEAR; + + /* ->populate can take a long time, so downgrade the lock. */ + downgrade_write(&mm->mmap_sem); + err = vma->vm_ops->populate(vma, start, size, + vma->vm_page_prot, + pgoff, flags & MAP_NONBLOCK); + + /* + * We can't clear VM_NONLINEAR because we'd have to do + * it after ->populate completes, and that would prevent + * downgrading the lock. (Locks can't be upgraded). + */ + up_read(&mm->mmap_sem); + } else { + up_write(&mm->mmap_sem); + } return err; } diff --git a/mm/memory.c b/mm/memory.c index 61b782f40df9..980953dbbfb4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -962,7 +961,6 @@ static inline void establish_pte(struct vm_area_struct * vma, unsigned long addr static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address, pte_t *page_table) { - invalidate_vcache(address, vma->vm_mm, new_page); flush_cache_page(vma, address); establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); } diff --git a/mm/vcache.c b/mm/vcache.c deleted file mode 100644 index 599e0f25490d..000000000000 --- a/mm/vcache.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * linux/mm/vcache.c - * - * virtual => physical page mapping cache. Users of this mechanism - * register callbacks for a given (virt,mm,phys) page mapping, and - * the kernel guarantees to call back when this mapping is invalidated. - * (ie. upon COW or unmap.) - * - * Started by Ingo Molnar, Copyright (C) 2002 - */ - -#include -#include -#include -#include - -#define VCACHE_HASHBITS 8 -#define VCACHE_HASHSIZE (1 << VCACHE_HASHBITS) - -spinlock_t vcache_lock = SPIN_LOCK_UNLOCKED; - -static struct list_head hash[VCACHE_HASHSIZE]; - -static struct list_head *hash_vcache(unsigned long address, - struct mm_struct *mm) -{ - return &hash[hash_long(address + (unsigned long)mm, VCACHE_HASHBITS)]; -} - -void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new)) -{ - struct list_head *hash_head; - - address &= PAGE_MASK; - vcache->address = address; - vcache->mm = mm; - vcache->callback = callback; - - hash_head = hash_vcache(address, mm); - - list_add_tail(&vcache->hash_entry, hash_head); -} - -void __detach_vcache(vcache_t *vcache) -{ - list_del_init(&vcache->hash_entry); -} - -void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page) -{ - struct list_head *l, *hash_head; - vcache_t *vcache; - - address &= PAGE_MASK; - - hash_head = hash_vcache(address, mm); - /* - * This is safe, because this path is called with the pagetable - * lock held. So while other mm's might add new entries in - * parallel, *this* mm is locked out, so if the list is empty - * now then we do not have to take the vcache lock to see it's - * really empty. - */ - if (likely(list_empty(hash_head))) - return; - - spin_lock(&vcache_lock); - list_for_each(l, hash_head) { - vcache = list_entry(l, vcache_t, hash_entry); - if (vcache->address != address || vcache->mm != mm) - continue; - vcache->callback(vcache, new_page); - } - spin_unlock(&vcache_lock); -} - -static int __init vcache_init(void) -{ - unsigned int i; - - for (i = 0; i < VCACHE_HASHSIZE; i++) - INIT_LIST_HEAD(hash + i); - return 0; -} -__initcall(vcache_init); - -- cgit v1.2.3 From 8ac8157022e788bb5c5ca3589f8025825f904c2a Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 4 Sep 2003 18:28:38 -0700 Subject: [PATCH] incomplete asm constraints in arch/i386/pci/pcbios.c This fixes a "miscompile" HP reported against gcc 3.3 with -march-pentium4. It turned out to be a non-complete asm contraint. the existing constraint on "opt" was on the address of "opt", which allowed gcc to reorder the setting of the fields inside opt to beyond the asm that uses it, which is less than useful at best. --- arch/i386/pci/pcbios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 9e8ff72c542f..8db66f34640f 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -430,7 +430,8 @@ struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) "xor %%ah, %%ah\n" "1:" : "=a" (ret), - "=b" (map) + "=b" (map), + "+m" (opt) : "0" (PCIBIOS_GET_ROUTING_OPTIONS), "1" (0), "D" ((long) &opt), -- cgit v1.2.3 From 85a98c385333e7c69f8c242ba41a6c0998271c57 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Thu, 4 Sep 2003 18:45:12 -0700 Subject: [PATCH] 2.6.0-test4 synclink.c * add RCC underrun handling * fix stats output typo * replace previously removed NULL context check (causes oops when opening non existent device) --- drivers/char/synclink.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index bf80e670091d..e55e9abb184d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.12 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink.c,v 4.16 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -261,6 +261,7 @@ struct mgsl_struct { int rx_enabled; int rx_overflow; + int rx_rcc_underrun; int tx_enabled; int tx_active; @@ -910,7 +911,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.16 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -983,6 +984,9 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } @@ -1125,7 +1129,16 @@ void mgsl_bh_receive(struct mgsl_struct *info) printk( "%s(%d):mgsl_bh_receive(%s)\n", __FILE__,__LINE__,info->device_name); - while( (get_rx_frame)(info) ); + do + { + if (info->rx_rcc_underrun) { + unsigned long flags; + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return; + } + } while(get_rx_frame(info)); } void mgsl_bh_transmit(struct mgsl_struct *info) @@ -1567,6 +1580,21 @@ void mgsl_isr_misc( struct mgsl_struct *info ) printk("%s(%d):mgsl_isr_misc status=%04X\n", __FILE__,__LINE__,status); + if ((status & MISCSTATUS_RCC_UNDERRUN) && + (info->params.mode == MGSL_MODE_HDLC)) { + + /* turn off receiver and rx DMA */ + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + usc_DmaCmd(info, DmaCmd_ResetRxChannel); + usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); + + /* schedule BH handler to restart receiver */ + info->pending_bh |= BH_RECEIVE; + info->rx_rcc_underrun = 1; + } + usc_ClearIrqPendingBits( info, MISC ); usc_UnlatchMiscstatusBits( info, status ); @@ -3625,7 +3653,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info) if (info->icount.rxover) ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); } else { ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", info->icount.tx, info->icount.rx); @@ -5190,7 +5218,11 @@ void usc_set_sdlc_mode( struct mgsl_struct *info ) usc_EnableMasterIrqBit( info ); usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + - TRANSMIT_STATUS + TRANSMIT_DATA ); + TRANSMIT_STATUS + TRANSMIT_DATA + MISC); + + /* arm RCC underflow interrupt */ + usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); + usc_EnableInterrupts(info, MISC); info->mbre_bit = 0; outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ @@ -5628,6 +5660,7 @@ void usc_stop_receiver( struct mgsl_struct *info ) info->rx_enabled = 0; info->rx_overflow = 0; + info->rx_rcc_underrun = 0; } /* end of stop_receiver() */ -- cgit v1.2.3 From aaac19691c34aaacece57d9be61acc872c9253ff Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Thu, 4 Sep 2003 18:45:21 -0700 Subject: [PATCH] 2.6.0-test4 synclinkmp.c * replace previously removed NULL context check (causes oops when opening non existent device) --- drivers/char/synclinkmp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ae3d9c41b668..587dcb3a669d 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.12 2003/06/18 15:29:33 paulkf Exp $ + * $Id: synclinkmp.c,v 4.14 2003/09/05 15:26:03 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -496,7 +496,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.14 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -713,6 +713,9 @@ static inline int sanity_check(SLMP_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } -- cgit v1.2.3 From 863003968458edf00e2ebdad49f68040203d886d Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Thu, 4 Sep 2003 18:45:29 -0700 Subject: [PATCH] 2.6.0-test4 synclink_cs.c * replace previously removed NULL context check (causes oops when opening non existent device) --- drivers/char/pcmcia/synclink_cs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 3ecc2b9a666e..e14a3ce8928d 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.13 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink_cs.c,v 4.15 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -491,7 +491,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.13 $"; +static char *driver_version = "$Revision: 4.15 $"; static struct tty_driver *serial_driver; @@ -838,6 +838,9 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } -- cgit v1.2.3 From d0d4b058d5ea15dd80c0f1ab99b13f676898246a Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 13:06:36 +0100 Subject: [ARM] arch/arm/kernel/setup.c needs to include asm/cacheflush.h --- arch/arm/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index cb3a112f2905..1e16dd88c251 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 993618b8252b5e32eac8534de5c45b24a0c99802 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 13:18:02 +0100 Subject: [ARM] Fix wrong cache flush call for ARM1020 CPUs --- arch/arm/mm/proc-arm1020.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 1712b9682de9..4808a860d216 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -79,7 +79,7 @@ ENTRY(cpu_arm1020_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_arm1020_cache_clean_invalidate_all + bl arm1020_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. -- cgit v1.2.3 From d8376671e64016eca98b020682c0b920c0afdb70 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 18:18:14 +0100 Subject: [ARM] Newer binutils want -mcpu=xscale not -mxscale --- arch/arm/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c2181d7de0a7..c6c817b0f9ef 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -34,7 +34,7 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4 -Wa$(comma)-mxscale) +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4) arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 @@ -47,8 +47,9 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 -tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) +tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +# Need -Uarm for gcc < 3.x CFLAGS_BOOT :=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm CFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm AFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu -- cgit v1.2.3 From a350bc24ded3aabf571b39ea81f08d20c6749fec Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 18:28:53 +0100 Subject: [ARM] Restore preempt count before reporting unbalanced preempt count On ARM, we oops when we detect that an interrupt handler has unbalanced the preempt count. We should restore the preempt count when we started to handle the interrupt and then cause the oops. --- arch/arm/kernel/entry-armv.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 0a5c2ea51b99..f6f64875dfd4 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -772,8 +772,8 @@ __irq_svc: sub sp, sp, #S_FRAME_SIZE preempt_return: ldr r0, [r8, #TI_PREEMPT] @ read preempt value teq r0, r7 - strne r0, [r0, -r0] @ bug() str r9, [r8, #TI_PREEMPT] @ restore preempt count + strne r0, [r0, -r0] @ bug() #endif ldr r0, [sp, #S_PSR] @ irqs are already disabled msr spsr, r0 @@ -908,8 +908,8 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE #ifdef CONFIG_PREEMPT ldr r0, [r8, #TI_PREEMPT] teq r0, r7 - strne r0, [r0, -r0] str r9, [r8, #TI_PREEMPT] + strne r0, [r0, -r0] mov tsk, r8 #else get_thread_info tsk -- cgit v1.2.3 From 226b6932f8d1509e16bfc51ad85d4f6f9ff3074f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 18:36:50 +0100 Subject: [ARM] Don't read the CPU control reg back - it may be write only. Some ARM CPUs don't allow CP15 CR1 control register to be read. Therefore, to ensure that the value hits the control register on Xscale, read back the CP15 CR0 ID register instead. --- arch/arm/kernel/head.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 4b233763aa0c..4de9941c54e2 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -120,9 +120,9 @@ __turn_mmu_on: orr r0, r0, #2 @ ...........A. #endif mcr p15, 0, r0, c1, c0, 0 @ write control reg - mrc p15, 0, r0, c1, c0, 0 @ read it back. - mov r0, r0 - mov r0, r0 + mrc p15, 0, r3, c0, c0, 0 @ read id reg + mov r3, r3 + mov r3, r3 mov pc, lr /* -- cgit v1.2.3 From dccfefd2dd87fb3e1687e74880586280c3ca85c4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 18:42:14 +0100 Subject: [ARM] Fix ARM suspend-to-RAM. - Suspend and resume system devices. - If device suspend fails, don't suspend. --- arch/arm/kernel/pm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c index e4a71e4e438f..fbe2d7a89580 100644 --- a/arch/arm/kernel/pm.c +++ b/arch/arm/kernel/pm.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -36,18 +37,25 @@ int suspend(void) if (ret != 0) goto out; - device_suspend(3); + ret = device_suspend(3); + if (ret) + goto resume_legacy; local_irq_disable(); leds_event(led_stop); + sysdev_suspend(3); + ret = pm_do_suspend(); + sysdev_resume(); + leds_event(led_start); local_irq_enable(); device_resume(); + resume_legacy: pm_send_all(PM_RESUME, (void *)0); out: -- cgit v1.2.3 From 3a5dccf9ef176823e6faffa2c328d094e0d918bd Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 19:04:35 +0100 Subject: [ARM] Fix PXA and SA1100 suspend/resume - Don't write the current time back to the RTC on suspend - we may jump over a programmed wakeup alarm. - Restore SA1100 GPIO output state --- arch/arm/mach-pxa/pm.c | 15 ++++----------- arch/arm/mach-sa1100/pm.c | 9 +++++++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 98b4d76cf7c3..c8183c873e1a 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -12,6 +12,7 @@ */ #include +#include #include #include @@ -63,15 +64,11 @@ int pm_do_suspend(void) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; + unsigned long delta; int i; - cli(); - clf(); - - leds_event(led_stop); - /* preserve current time */ - RCNR = xtime.tv_sec; + delta = xtime.tv_sec - RCNR; /* * Temporary solution. This won't be necessary once @@ -184,16 +181,12 @@ int pm_do_suspend(void) RESTORE(FFIER); /* restore current time */ - xtime.tv_sec = RCNR; + xtime.tv_sec = RCNR + delta; #ifdef DEBUG printk(KERN_DEBUG "*** made it back from resume\n"); #endif - leds_event(led_start); - - sti(); - return 0; } diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index ca55d99f678e..5c37635429bd 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -57,9 +57,11 @@ enum { SLEEP_SAVE_SP = 0, int pm_do_suspend(void) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; + unsigned long delta, gpio; /* preserve current time */ - RCNR = xtime.tv_sec; + delta = xtime.tv_sec - RCNR; + gpio = GPLR; /* save vital registers */ SAVE(OSCR); @@ -112,6 +114,9 @@ int pm_do_suspend(void) RESTORE(Ser1SDCR0); + GPSR = gpio; + GPCR = ~gpio; + /* * Clear the peripheral sleep-hold bit. */ @@ -125,7 +130,7 @@ int pm_do_suspend(void) RESTORE(OIER); /* restore current time */ - xtime.tv_sec = RCNR; + xtime.tv_sec = RCNR + delta; return 0; } -- cgit v1.2.3 From f3b302527e8e004d392dfc5f7df9c94ef735a3a4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 19:10:57 +0100 Subject: [ARM] Don't sleep in cpufreq code if IRQs are disabled (during resume.) --- arch/arm/mach-sa1100/cpu-sa1110.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 87a0d789e34a..edb5eb8c9cd5 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -270,8 +270,12 @@ static int sa1110_target(struct cpufreq_policy *policy, * We wait 20ms to be safe. */ sdram_set_refresh(2); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(20 * HZ / 1000); + if (!irqs_disabled()) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(20 * HZ / 1000); + } else { + mdelay(20); + } /* * Reprogram the DRAM timings with interrupts disabled, and -- cgit v1.2.3 From 7b89f42fcd257e8d47a16b3871b22bf608609267 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2003 19:14:26 +0100 Subject: [ARM] Kill snprintf formatting warning. --- arch/arm/mach-integrator/impd1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 29608b2f91fa..15e2e27da2de 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -186,7 +186,7 @@ static int impd1_probe(struct device *dev) memset(d, 0, sizeof(struct amba_device)); snprintf(d->dev.bus_id, sizeof(d->dev.bus_id), - "lm%x:%5.5x", pdev->id, idev->offset >> 12); + "lm%x:%5.5lx", pdev->id, idev->offset >> 12); d->dev.parent = &pdev->dev; d->res.start = res->start + idev->offset; -- cgit v1.2.3 From b9e8bb61e47ed0631d93839d370a43e10b8c951c Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:11 -0700 Subject: [PATCH] large dev_t - second series (1/15) misc trivial cleanups --- arch/ia64/sn/io/hwgfs/ramfs.c | 3 +-- arch/m68k/atari/stram.c | 6 ------ arch/ppc/platforms/pmac_setup.c | 2 +- arch/um/drivers/ubd_kern.c | 3 --- drivers/base/map.c | 5 ----- drivers/block/DAC960.h | 32 -------------------------------- drivers/char/drm/drmP.h | 4 ---- drivers/char/rocket.c | 30 +++++++----------------------- drivers/char/tipar.c | 1 - drivers/char/tty_io.c | 14 +++++--------- drivers/ieee1394/ieee1394_types.h | 4 ---- drivers/md/dm-ioctl-v1.c | 2 +- drivers/md/dm-ioctl-v4.c | 2 +- drivers/md/linear.c | 1 - drivers/md/md.c | 1 - drivers/md/multipath.c | 1 - drivers/md/raid0.c | 1 - drivers/md/raid1.c | 1 - drivers/media/video/videodev.c | 2 +- drivers/media/video/zoran_driver.c | 2 +- drivers/s390/char/tubio.h | 18 ------------------ drivers/usb/core/inode.c | 1 - fs/afs/inode.c | 1 - fs/autofs4/inode.c | 1 - fs/devfs/base.c | 5 ++--- fs/hfs/inode.c | 1 - fs/hugetlbfs/inode.c | 1 - fs/jffs/inode-v23.c | 1 - fs/jffs2/fs.c | 2 +- fs/ncpfs/inode.c | 1 - fs/ramfs/inode.c | 1 - fs/romfs/inode.c | 6 ++---- fs/sysfs/inode.c | 1 - mm/shmem.c | 1 - 34 files changed, 23 insertions(+), 135 deletions(-) diff --git a/arch/ia64/sn/io/hwgfs/ramfs.c b/arch/ia64/sn/io/hwgfs/ramfs.c index 0ec5807cc73a..5a112ccbfd27 100644 --- a/arch/ia64/sn/io/hwgfs/ramfs.c +++ b/arch/ia64/sn/io/hwgfs/ramfs.c @@ -56,7 +56,7 @@ static struct backing_dev_info hwgfs_backing_dev_info = { .memory_backed = 1, /* Does not contribute to dirty memory */ }; -struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) +static struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode * inode = new_inode(sb); @@ -66,7 +66,6 @@ struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &hwgfs_aops; inode->i_mapping->backing_dev_info = &hwgfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 95152f2f2c65..3e3531a38a13 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -34,12 +34,6 @@ #include -#ifdef CONFIG_STRAM_SWAP -#define MAJOR_NR Z2RAM_MAJOR -#define do_z2_request do_stram_request -#define DEVICE_NR(device) (minor(device)) -#endif - #undef DEBUG #ifdef DEBUG diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index 15de29c7b588..189e8d0d18b8 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -399,7 +399,7 @@ note_scsi_host(struct device_node *node, void *host) #endif #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -dev_t __init +static dev_t __init find_ide_boot(void) { char *p; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 39fa46ec2db6..0c3890b3ea12 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -55,9 +55,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); #define MAX_DEV (8) -#define MAX_MINOR (MAX_DEV << UBD_SHIFT) - -#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, diff --git a/drivers/base/map.c b/drivers/base/map.c index 0fc8e3a10756..af7ae91d8145 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c @@ -28,11 +28,6 @@ struct kobj_map { struct rw_semaphore *sem; }; -static inline int dev_to_index(dev_t dev) -{ - return MAJOR(dev) % 255; -} - int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, struct module *module, kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data) diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index 14b90438a30f..28fb52af3af4 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -2063,38 +2063,6 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); #define DAC960_MaxPartitions 8 #define DAC960_MaxPartitionsBits 3 - -/* - Define macros to extract the Controller Number, Logical Drive Number, and - Partition Number from a Kernel Device, and to construct a Major Number, Minor - Number, and Kernel Device from the Controller Number, Logical Drive Number, - and Partition Number. There is one Major Number assigned to each Controller. - The associated Minor Number is divided into the Logical Drive Number and - Partition Number. -*/ - -#define DAC960_ControllerNumber(Device) \ - (major(Device) - DAC960_MAJOR) - -#define DAC960_LogicalDriveNumber(Device) \ - (minor(Device) >> DAC960_MaxPartitionsBits) - -#define DAC960_MajorNumber(ControllerNumber) \ - (DAC960_MAJOR + (ControllerNumber)) - -#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \ - (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber)) - -#define DAC960_MinorCount (DAC960_MaxLogicalDrives \ - * DAC960_MaxPartitions) - -#define DAC960_KernelDevice(ControllerNumber, \ - LogicalDriveNumber, \ - PartitionNumber) \ - mk_kdev(DAC960_MajorNumber(ControllerNumber), \ - DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber)) - - /* Define the DAC960 Controller fixed Block Size and Block Size Bits. */ diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index b410b22f907e..2cfca61b9801 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -158,10 +158,6 @@ /** \name Backward compatibility section */ /*@{*/ -#ifndef minor -#define minor(x) MINOR((x)) -#endif - #ifndef MODULE_LICENSE #define MODULE_LICENSE(x) #endif diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 4275bb8521f0..8f969928c68b 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1460,17 +1460,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, return 0; } -#if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE)) -static char *rp_tty_name(struct tty_struct *tty, char *buf) -{ - if (tty) - sprintf(buf, "%s%d", TTY_DRIVER_NAME(tty), MINOR(tty->device) - TTY_DRIVER_MINOR_START(tty) + TTY_DRIVER_NAME_BASE); - else - strcpy(buf, "NULL tty"); - return buf; -} -#endif - static void rp_send_xchar(struct tty_struct *tty, char ch) { struct r_port *info = (struct r_port *) tty->driver_data; @@ -1490,10 +1479,9 @@ static void rp_throttle(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; -#ifdef ROCKET_DEBUG_THROTTLE - char buf[64]; - printk(KERN_INFO "throttle %s: %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_THROTTLE + printk(KERN_INFO "throttle %s: %d....\n", tty->name, tty->ldisc.chars_in_buffer(tty)); #endif @@ -1512,9 +1500,7 @@ static void rp_unthrottle(struct tty_struct *tty) struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; #ifdef ROCKET_DEBUG_THROTTLE - char buf[64]; - - printk(KERN_INFO "unthrottle %s: %d....\n", rp_tty_name(tty, buf), + printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, tty->ldisc.chars_in_buffer(tty)); #endif @@ -1539,10 +1525,9 @@ static void rp_unthrottle(struct tty_struct *tty) static void rp_stop(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; -#ifdef ROCKET_DEBUG_FLOW - char buf[64]; - printk(KERN_INFO "stop %s: %d %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "stop %s: %d %d....\n", tty->name, info->xmit_cnt, info->xmit_fifo_room); #endif @@ -1556,10 +1541,9 @@ static void rp_stop(struct tty_struct *tty) static void rp_start(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; -#ifdef ROCKET_DEBUG_FLOW - char buf[64]; - printk(KERN_INFO "start %s: %d %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "start %s: %d %d....\n", tty->name, info->xmit_cnt, info->xmit_fifo_room); #endif diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 660f7b0f1487..fc1558cab6e0 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -74,7 +74,6 @@ #define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) #if LINUX_VERSION_CODE < VERSION(2,5,0) -# define minor(x) MINOR(x) # define need_resched() (current->need_resched) #endif diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index aab1780082fc..5b4693c5f990 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2140,7 +2140,7 @@ error: kfree(tty_dev); } -void tty_remove_class_device(dev_t dev) +static void tty_remove_class_device(dev_t dev) { struct tty_dev *tty_dev = NULL; struct list_head *tmp; @@ -2149,19 +2149,15 @@ void tty_remove_class_device(dev_t dev) spin_lock(&tty_dev_list_lock); list_for_each (tmp, &tty_dev_list) { tty_dev = list_entry(tmp, struct tty_dev, node); - if ((MAJOR(tty_dev->dev) == MAJOR(dev)) && - (MINOR(tty_dev->dev) == MINOR(dev))) { + if (tty_dev->dev == dev) { + list_del(&tty_dev->node); found = 1; break; } } - if (found) { - list_del(&tty_dev->node); - spin_unlock(&tty_dev_list_lock); + spin_unlock(&tty_dev_list_lock); + if (found) class_device_unregister(&tty_dev->class_dev); - } else { - spin_unlock(&tty_dev_list_lock); - } } /** diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index e2e8ec8d78a5..60efa9ec9a07 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -16,10 +16,6 @@ /* The great kdev_t changeover in 2.5.x */ #include -#ifndef minor -#define minor(dev) MINOR(dev) -#endif - /* Transaction Label handling */ struct hpsb_tlabel_pool { diff --git a/drivers/md/dm-ioctl-v1.c b/drivers/md/dm-ioctl-v1.c index 3afe5e55ae66..0dc24d76de3f 100644 --- a/drivers/md/dm-ioctl-v1.c +++ b/drivers/md/dm-ioctl-v1.c @@ -577,7 +577,7 @@ static int create(struct dm_ioctl *param, struct dm_ioctl *user) } if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + r = dm_create_with_minor(MINOR(param->dev), &md); else r = dm_create(&md); diff --git a/drivers/md/dm-ioctl-v4.c b/drivers/md/dm-ioctl-v4.c index 2c8243aab6f5..0ea9a58b8daf 100644 --- a/drivers/md/dm-ioctl-v4.c +++ b/drivers/md/dm-ioctl-v4.c @@ -481,7 +481,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) return r; if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + r = dm_create_with_minor(MINOR(param->dev), &md); else r = dm_create(&md); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 9da446a143ec..322782c4cda2 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -25,7 +25,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) /* * find which device holds a particular offset diff --git a/drivers/md/md.c b/drivers/md/md.c index b95a323cdf41..6a67e10393e2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -50,7 +50,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER -#define DEVICE_NR(device) (minor(device)) #define DEBUG 0 #define dprintk(x...) ((void)(DEBUG && printk(x))) diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 4d19a4bd6808..afa7e3e87b21 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -29,7 +29,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) #define MAX_WORK_PER_DISK 128 diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index eb4368751307..ad7a468c6831 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -24,7 +24,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) static int create_strip_zones (mddev_t *mddev) { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index cb7acbfb87cf..83533c262986 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -27,7 +27,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) /* * Number of guaranteed r1bios in case of extreme VM load: diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 777f59a1f6c9..e7d60fcfbb12 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -52,7 +52,7 @@ static ssize_t show_dev(struct class_device *cd, char *buf) { struct video_device *vfd = container_of(cd, struct video_device, class_dev); dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor); - return sprintf(buf,"%04x\n",(int)dev); + return sprintf(buf,"%04x\n",old_encode_dev(dev)); } static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index bd5b10bbc08d..6cc67f746eb2 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -1265,7 +1265,7 @@ static int zoran_open (struct inode *inode, struct file *file) { - unsigned int minor = minor(inode->i_rdev); + unsigned int minor = iminor(inode); struct zoran *zr = NULL; struct zoran_fh *fh; int i, res, first_open = 0, have_module_locks = 0; diff --git a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h index 92cd4fe8dbd1..cd04879e4048 100644 --- a/drivers/s390/char/tubio.h +++ b/drivers/s390/char/tubio.h @@ -158,7 +158,6 @@ enum tubwhat { /* echo what= proc actions */ #define TUBMAXMINS 256 -#define TUB_DEV MKDEV(IBM_FS3270_MAJ, 0) /* Generic /dev/3270/tub */ #define _GEOM_ROWS 24 #define _GEOM_COLS 80 #define GEOM_ROWS (tubp->geom_rows) @@ -294,23 +293,6 @@ typedef struct tub_s { #define TUB_UE_BUSY 0x0800 #define TUB_INPUT_HACK 0x1000 /* Early init of command line */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -#define S390_CONSOLE_DEV MKDEV(TTY_MAJOR, 64) -#define tub_major(x) MAJOR(x) -#define tub_minor(x) MINOR(x) -#define tub_mkdev(x, y) MKDEV(x, y) -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#define S390_CONSOLE_DEV MKDEV(TTYAUX_MAJOR, 1) -#define tub_major(x) MAJOR(x) -#define tub_minor(x) MINOR(x) -#define tub_mkdev(x, y) MKDEV(x, y) -#else -#define S390_CONSOLE_DEV mk_kdev(TTYAUX_MAJOR, 1) -#define tub_major(x) major(x) -#define tub_minor(x) minor(x) -#define tub_mkdev(x, y) mk_kdev(x, y) -#endif - /* * Extra stuff for 3270 console support */ diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 870900b513da..8474deb3f277 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -152,7 +152,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; switch (mode & S_IFMT) { default: diff --git a/fs/afs/inode.c b/fs/afs/inode.c index a58e32b26acb..1c83000f2c3d 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -68,7 +68,6 @@ static int afs_inode_map_status(afs_vnode_t *vnode) inode->i_nlink = vnode->status.nlink; inode->i_uid = vnode->status.owner; inode->i_gid = 0; - inode->i_rdev = NODEV; inode->i_size = vnode->status.size; inode->i_atime.tv_sec = inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = vnode->status.mtime_server; inode->i_atime.tv_nsec = diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 090a7e961c08..35647d8eca94 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -298,7 +298,6 @@ struct inode *autofs4_get_inode(struct super_block *sb, } inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; if (S_ISDIR(inf->mode)) { diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 69a91269e0e9..3df3c5dc1697 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2010,7 +2010,6 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb, inode->i_blksize = FAKE_BLOCK_SIZE; inode->i_op = &devfs_iops; inode->i_fop = &devfs_fops; - inode->i_rdev = NODEV; if ( S_ISCHR (de->mode) ) { inode->i_rdev = to_kdev_t(de->u.cdev.dev); @@ -2494,8 +2493,8 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode, struct devfs_entry *parent, *de; struct inode *inode; - DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %d\n", - dentry->d_name.name, mode, rdev); + DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", + dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); parent = get_devfs_entry_from_vfs_inode (dir); if (parent == NULL) return -ENOENT; de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode); diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 21f14fcf8ccf..398de286c3e7 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -322,7 +322,6 @@ struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type, /* Initialize the inode */ struct hfs_sb_info *hsb = HFS_SB(sb); - inode->i_rdev = NODEV; inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec = hfs_m_to_utime(entry->modify_date); inode->i_ctime.tv_nsec = 0; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 7b196a5024ae..effaa5bc5a96 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -406,7 +406,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_gid = gid; inode->i_blksize = HPAGE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &hugetlbfs_aops; inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 77b102d65299..480a5ba41972 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -362,7 +362,6 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, inode->i_nlink = raw_inode->nlink; inode->i_uid = raw_inode->uid; inode->i_gid = raw_inode->gid; - inode->i_rdev = NODEV; inode->i_size = raw_inode->dsize; inode->i_atime.tv_sec = raw_inode->atime; inode->i_mtime.tv_sec = raw_inode->mtime; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 4c43d597d0aa..88464374eaf1 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -147,7 +147,7 @@ void jffs2_read_inode (struct inode *inode) case S_IFSOCK: case S_IFIFO: inode->i_op = &jffs2_file_inode_operations; - init_special_inode(inode, inode->i_mode, kdev_t_to_nr(mk_kdev(je16_to_cpu(rdev)>>8, je16_to_cpu(rdev)&0xff))); + init_special_inode(inode, inode->i_mode, MKDEV(je16_to_cpu(rdev)>>8, je16_to_cpu(rdev)&0xff)); break; default: diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 70eab7961377..d0bd5276de56 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -220,7 +220,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) inode->i_nlink = 1; inode->i_uid = server->m.uid; inode->i_gid = server->m.gid; - inode->i_rdev = NODEV; inode->i_blksize = NCP_BLOCK_SIZE; ncp_update_dates(inode, &nwinfo->i); diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 362ee3135e69..267691bb5174 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -58,7 +58,6 @@ static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &ramfs_aops; inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 24cd428a521e..80b17af9bb0d 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -542,10 +542,8 @@ romfs_read_inode(struct inode *i) default: /* depending on MBZ for sock/fifos */ nextfh = ntohl(ri.spec); - /* convert back and forth for typechecking and - * source tagging */ - nextfh = kdev_t_to_nr(mk_kdev(nextfh>>16,nextfh&0xffff)); - init_special_inode(i, ino, nextfh); + init_special_inode(i, ino, + MKDEV(nextfh>>16,nextfh&0xffff)); } } diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index c22313b1fa7a..965b5e9eaba1 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -33,7 +33,6 @@ struct inode * sysfs_new_inode(mode_t mode) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; diff --git a/mm/shmem.c b/mm/shmem.c index a106bfec7709..bb429eee7ebd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1040,7 +1040,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; -- cgit v1.2.3 From 890b6a7a84ab1f17e144b8e9d0ea0f3af92be306 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:20 -0700 Subject: [PATCH] large dev_t - second series (2/15) floppy98 ->probe() forgot to set *part to 0; fixed. --- drivers/block/floppy98.c | 1 + fs/partitions/nec98.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/floppy98.c b/drivers/block/floppy98.c index d861fdbc3466..9513de5f11cf 100644 --- a/drivers/block/floppy98.c +++ b/drivers/block/floppy98.c @@ -4249,6 +4249,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) return NULL; if (((*part>>2) & 0x1f) >= NUMBER(floppy_type)) return NULL; + *part = 0; return get_disk(disks[drive]); } diff --git a/fs/partitions/nec98.c b/fs/partitions/nec98.c index 5f78e5b4895c..08c72aecea1f 100644 --- a/fs/partitions/nec98.c +++ b/fs/partitions/nec98.c @@ -73,10 +73,9 @@ int nec98_partition(struct parsed_partitions *state, struct block_device *bdev) const struct nec98_partition *part; unsigned char *data; int sector_size = bdev_hardsect_size(bdev); - int major = MAJOR(bdev->bd_dev); if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) { - printk(" unsupported disk (major = %u)\n", major); + printk(" unsupported disk (%s)\n", bdev->bd_disk->disk_name); return 0; } -- cgit v1.2.3 From 98ba005d88222330b03470ee3fe5c4ddffa3cfff Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:29 -0700 Subject: [PATCH] large dev_t - second series (3/15) paride/pt.c cleanups - passing pointer to pt_unit instead of index in array; same as had been done for pd/pcd/pf. --- drivers/block/paride/pt.c | 505 ++++++++++++++++++++++------------------------ 1 file changed, 245 insertions(+), 260 deletions(-) diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index feb1d9950dc7..7db4fc7584c0 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -126,7 +126,6 @@ static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; -static int pt_drive_count; #define D_PRT 0 #define D_PRO 1 @@ -218,9 +217,7 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos); static int pt_detect(void); -static int pt_identify(int unit); - -/* bits in PT.flags */ +/* bits in tape->flags */ #define PT_MEDIA 1 #define PT_WRITE_OK 2 @@ -246,12 +243,9 @@ struct pt_unit { char name[PT_NAMELEN]; /* pf0, pf1, ... */ }; -struct pt_unit pt[PT_UNITS]; - -/* 'unit' must be defined in all functions - either as a local or a param */ +static int pt_identify(struct pt_unit *tape); -#define PT pt[unit] -#define PI PT.pi +struct pt_unit pt[PT_UNITS]; static char pt_scratch[512]; /* scratch block buffer */ @@ -266,156 +260,139 @@ static struct file_operations pt_fops = { .release = pt_release, }; -static void pt_init_units(void) +static inline int status_reg(struct pi_adapter *pi) { - int unit, j; - - pt_drive_count = 0; - for (unit = 0; unit < PT_UNITS; unit++) { - PT.pi = &PT.pia; - atomic_set(&PT.available, 1); - PT.flags = 0; - PT.last_sense = 0; - PT.present = 0; - PT.bufptr = NULL; - PT.drive = DU[D_SLV]; - j = 0; - while ((j < PT_NAMELEN - 2) && (PT.name[j] = name[j])) - j++; - PT.name[j++] = '0' + unit; - PT.name[j] = 0; - if (DU[D_PRT]) - pt_drive_count++; - } + return pi_read_regr(pi, 1, 6); } -static inline int status_reg(int unit) +static inline int read_reg(struct pi_adapter *pi, int reg) { - return pi_read_regr(PI, 1, 6); + return pi_read_regr(pi, 0, reg); } -static inline int read_reg(int unit, int reg) +static inline void write_reg(struct pi_adapter *pi, int reg, int val) { - return pi_read_regr(PI, 0, reg); + pi_write_regr(pi, 0, reg, val); } -static inline void write_reg(int unit, int reg, int val) +static inline u8 DRIVE(struct pt_unit *tape) { - pi_write_regr(PI, 0, reg, val); + return 0xa0+0x10*tape->drive; } -#define DRIVE (0xa0+0x10*PT.drive) - -static int pt_wait(int unit, int go, int stop, char *fun, char *msg) +static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg) { int j, r, e, s, p; + struct pi_adapter *pi = tape->pi; j = 0; - while ((((r = status_reg(unit)) & go) || (stop && (!(r & stop)))) + while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop)))) && (j++ < PT_SPIN)) udelay(PT_SPIN_DEL); if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) { - s = read_reg(unit, 7); - e = read_reg(unit, 1); - p = read_reg(unit, 2); + s = read_reg(pi, 7); + e = read_reg(pi, 1); + p = read_reg(pi, 2); if (j >= PT_SPIN) e |= 0x100; if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" " loop=%d phase=%d\n", - PT.name, fun, msg, r, s, e, j, p); + tape->name, fun, msg, r, s, e, j, p); return (e << 8) + s; } return 0; } -static int pt_command(int unit, char *cmd, int dlen, char *fun) +static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun) { - pi_connect(PI); + struct pi_adapter *pi = tape->pi; + pi_connect(pi); - write_reg(unit, 6, DRIVE); + write_reg(pi, 6, DRIVE(tape)); - if (pt_wait(unit, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { - pi_disconnect(PI); + if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { + pi_disconnect(pi); return -1; } - write_reg(unit, 4, dlen % 256); - write_reg(unit, 5, dlen / 256); - write_reg(unit, 7, 0xa0); /* ATAPI packet command */ + write_reg(pi, 4, dlen % 256); + write_reg(pi, 5, dlen / 256); + write_reg(pi, 7, 0xa0); /* ATAPI packet command */ - if (pt_wait(unit, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { - pi_disconnect(PI); + if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { + pi_disconnect(pi); return -1; } - if (read_reg(unit, 2) != 1) { - printk("%s: %s: command phase error\n", PT.name, fun); - pi_disconnect(PI); + if (read_reg(pi, 2) != 1) { + printk("%s: %s: command phase error\n", tape->name, fun); + pi_disconnect(pi); return -1; } - pi_write_block(PI, cmd, 12); + pi_write_block(pi, cmd, 12); return 0; } -static int pt_completion(int unit, char *buf, char *fun) +static int pt_completion(struct pt_unit *tape, char *buf, char *fun) { + struct pi_adapter *pi = tape->pi; int r, s, n, p; - r = pt_wait(unit, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, fun, "completion"); - if (read_reg(unit, 7) & STAT_DRQ) { - n = (((read_reg(unit, 4) + 256 * read_reg(unit, 5)) + + if (read_reg(pi, 7) & STAT_DRQ) { + n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) + 3) & 0xfffc); - p = read_reg(unit, 2) & 3; + p = read_reg(pi, 2) & 3; if (p == 0) - pi_write_block(PI, buf, n); + pi_write_block(pi, buf, n); if (p == 2) - pi_read_block(PI, buf, n); + pi_read_block(pi, buf, n); } - s = pt_wait(unit, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); + s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); - pi_disconnect(PI); + pi_disconnect(pi); return (r ? r : s); } -static void pt_req_sense(int unit, int quiet) +static void pt_req_sense(struct pt_unit *tape, int quiet) { char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; char buf[16]; int r; - r = pt_command(unit, rs_cmd, 16, "Request sense"); + r = pt_command(tape, rs_cmd, 16, "Request sense"); mdelay(1); if (!r) - pt_completion(unit, buf, "Request sense"); + pt_completion(tape, buf, "Request sense"); - PT.last_sense = -1; + tape->last_sense = -1; if (!r) { if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - PT.name, buf[2] & 0xf, buf[12], buf[13]); - PT.last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) + tape->name, buf[2] & 0xf, buf[12], buf[13]); + tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16); } } -static int pt_atapi(int unit, char *cmd, int dlen, char *buf, char *fun) +static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun) { int r; - r = pt_command(unit, cmd, dlen, fun); + r = pt_command(tape, cmd, dlen, fun); mdelay(1); if (!r) - r = pt_completion(unit, buf, fun); + r = pt_completion(tape, buf, fun); if (r) - pt_req_sense(unit, !fun); + pt_req_sense(tape, !fun); return r; } @@ -426,8 +403,9 @@ static void pt_sleep(int cs) schedule_timeout(cs); } -static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) +static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg) { + struct pi_adapter *pi = tape->pi; int k, e, s; k = 0; @@ -436,94 +414,95 @@ static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) while (k < tmo) { pt_sleep(pause); k++; - pi_connect(PI); - write_reg(unit, 6, DRIVE); - s = read_reg(unit, 7); - e = read_reg(unit, 1); - pi_disconnect(PI); + pi_connect(pi); + write_reg(pi, 6, DRIVE(tape)); + s = read_reg(pi, 7); + e = read_reg(pi, 1); + pi_disconnect(pi); if (s & (STAT_ERR | STAT_SEEK)) break; } if ((k >= tmo) || (s & STAT_ERR)) { if (k >= tmo) - printk("%s: %s DSC timeout\n", PT.name, msg); + printk("%s: %s DSC timeout\n", tape->name, msg); else - printk("%s: %s stat=0x%x err=0x%x\n", PT.name, msg, s, + printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s, e); - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return 0; } return 1; } -static void pt_media_access_cmd(int unit, int tmo, char *cmd, char *fun) +static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun) { - if (pt_command(unit, cmd, 0, fun)) { - pt_req_sense(unit, 0); + if (pt_command(tape, cmd, 0, fun)) { + pt_req_sense(tape, 0); return; } - pi_disconnect(PI); - pt_poll_dsc(unit, HZ, tmo, fun); + pi_disconnect(tape->pi); + pt_poll_dsc(tape, HZ, tmo, fun); } -static void pt_rewind(int unit) +static void pt_rewind(struct pt_unit *tape) { char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - pt_media_access_cmd(unit, PT_REWIND_TMO, rw_cmd, "rewind"); + pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind"); } -static void pt_write_fm(int unit) +static void pt_write_fm(struct pt_unit *tape) { char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; - pt_media_access_cmd(unit, PT_TMO, wm_cmd, "write filemark"); + pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark"); } #define DBMSG(msg) ((verbose>1)?(msg):NULL) -static int pt_reset(int unit) +static int pt_reset(struct pt_unit *tape) { + struct pi_adapter *pi = tape->pi; int i, k, flg; int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - pi_connect(PI); - write_reg(unit, 6, DRIVE); - write_reg(unit, 7, 8); + pi_connect(pi); + write_reg(pi, 6, DRIVE(tape)); + write_reg(pi, 7, 8); pt_sleep(20 * HZ / 1000); k = 0; - while ((k++ < PT_RESET_TMO) && (status_reg(unit) & STAT_BUSY)) + while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY)) pt_sleep(HZ / 10); flg = 1; for (i = 0; i < 5; i++) - flg &= (read_reg(unit, i + 1) == expect[i]); + flg &= (read_reg(pi, i + 1) == expect[i]); if (verbose) { - printk("%s: Reset (%d) signature = ", PT.name, k); + printk("%s: Reset (%d) signature = ", tape->name, k); for (i = 0; i < 5; i++) - printk("%3x", read_reg(unit, i + 1)); + printk("%3x", read_reg(pi, i + 1)); if (!flg) printk(" (incorrect)"); printk("\n"); } - pi_disconnect(PI); + pi_disconnect(pi); return flg - 1; } -static int pt_ready_wait(int unit, int tmo) +static int pt_ready_wait(struct pt_unit *tape, int tmo) { char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, p; k = 0; while (k < tmo) { - PT.last_sense = 0; - pt_atapi(unit, tr_cmd, 0, NULL, DBMSG("test unit ready")); - p = PT.last_sense; + tape->last_sense = 0; + pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready")); + p = tape->last_sense; if (!p) return 0; if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) @@ -558,7 +537,7 @@ static int xn(char *buf, int offs, int size) return v; } -static int pt_identify(int unit) +static int pt_identify(struct pt_unit *tape) { int dt, s; char *ms[2] = { "master", "slave" }; @@ -570,7 +549,7 @@ static int pt_identify(int unit) { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 }; char buf[36]; - s = pt_atapi(unit, id_cmd, 36, buf, "identify"); + s = pt_atapi(tape, id_cmd, 36, buf, "identify"); if (s) return -1; @@ -578,36 +557,36 @@ static int pt_identify(int unit) if (dt != 1) { if (verbose) printk("%s: Drive %d, unsupported type %d\n", - PT.name, PT.drive, dt); + tape->name, tape->drive, dt); return -1; } xs(buf, mf, 8, 8); xs(buf, id, 16, 16); - PT.flags = 0; - PT.capacity = 0; - PT.bs = 0; + tape->flags = 0; + tape->capacity = 0; + tape->bs = 0; - if (!pt_ready_wait(unit, PT_READY_TMO)) - PT.flags |= PT_MEDIA; + if (!pt_ready_wait(tape, PT_READY_TMO)) + tape->flags |= PT_MEDIA; - if (!pt_atapi(unit, ms_cmd, 36, buf, "mode sense")) { + if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) { if (!(buf[2] & 0x80)) - PT.flags |= PT_WRITE_OK; - PT.bs = xn(buf, 10, 2); + tape->flags |= PT_WRITE_OK; + tape->bs = xn(buf, 10, 2); } - if (!pt_atapi(unit, ls_cmd, 36, buf, "log sense")) - PT.capacity = xn(buf, 24, 4); + if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense")) + tape->capacity = xn(buf, 24, 4); - printk("%s: %s %s, %s", PT.name, mf, id, ms[PT.drive]); - if (!(PT.flags & PT_MEDIA)) + printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]); + if (!(tape->flags & PT_MEDIA)) printk(", no media\n"); else { - if (!(PT.flags & PT_WRITE_OK)) + if (!(tape->flags & PT_WRITE_OK)) printk(", RO"); - printk(", blocksize %d, %d MB\n", PT.bs, PT.capacity / 1024); + printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024); } return 0; @@ -618,109 +597,117 @@ static int pt_identify(int unit) * returns 0, with id set if drive is detected * -1, if drive detection failed */ -static int pt_probe(int unit) +static int pt_probe(struct pt_unit *tape) { - if (PT.drive == -1) { - for (PT.drive = 0; PT.drive <= 1; PT.drive++) - if (!pt_reset(unit)) - return pt_identify(unit); + if (tape->drive == -1) { + for (tape->drive = 0; tape->drive <= 1; tape->drive++) + if (!pt_reset(tape)) + return pt_identify(tape); } else { - if (!pt_reset(unit)) - return pt_identify(unit); + if (!pt_reset(tape)) + return pt_identify(tape); } return -1; } static int pt_detect(void) { - int k, unit; + struct pt_unit *tape; + int specified = 0, found = 0; + int unit; printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major); - k = 0; - if (pt_drive_count == 0) { - unit = 0; - if (pi_init(PI, 1, -1, -1, -1, -1, -1, pt_scratch, - PI_PT, verbose, PT.name)) { - if (!pt_probe(unit)) { - PT.present = 1; - k++; + specified = 0; + for (unit = 0; unit < PT_UNITS; unit++) { + struct pt_unit *tape = &pt[unit]; + tape->pi = &tape->pia; + atomic_set(&tape->available, 1); + tape->flags = 0; + tape->last_sense = 0; + tape->present = 0; + tape->bufptr = NULL; + tape->drive = DU[D_SLV]; + snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit); + if (!DU[D_PRT]) + continue; + specified++; + if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], + DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT, + verbose, tape->name)) { + if (!pt_probe(tape)) { + tape->present = 1; + found++; } else - pi_release(PI); + pi_release(tape->pi); + } + } + if (specified == 0) { + tape = pt; + if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch, + PI_PT, verbose, tape->name)) { + if (!pt_probe(tape)) { + tape->present = 1; + found++; + } else + pi_release(tape->pi); } - } else - for (unit = 0; unit < PT_UNITS; unit++) - if (DU[D_PRT]) - if (pi_init - (PI, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], - DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT, - verbose, PT.name)) { - if (!pt_probe(unit)) { - PT.present = 1; - k++; - } else - pi_release(PI); - } - - if (k) + } + if (found) return 0; printk("%s: No ATAPI tape drive detected\n", name); return -1; } -#define DEVICE_NR(inode) (iminor(inode) & 0x7F) - static int pt_open(struct inode *inode, struct file *file) { - int unit = DEVICE_NR(inode); + int unit = iminor(inode) & 0x7F; + struct pt_unit *tape = pt + unit; + int err; - if ((unit >= PT_UNITS) || (!PT.present)) + if (unit >= PT_UNITS || (!tape->present)) return -ENODEV; - if (!atomic_dec_and_test(&PT.available)) { - atomic_inc(&PT.available); - return -EBUSY; - } + err = -EBUSY; + if (!atomic_dec_and_test(&tape->available)) + goto out; - pt_identify(unit); + pt_identify(tape); - if (!PT.flags & PT_MEDIA) { - atomic_inc(&PT.available); - return -ENODEV; - } + err = -ENODEV; + if (!tape->flags & PT_MEDIA) + goto out; - if ((!PT.flags & PT_WRITE_OK) && (file->f_mode & 2)) { - atomic_inc(&PT.available); - return -EROFS; - } + err = -EROFS; + if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2)) + goto out; if (!(iminor(inode) & 128)) - PT.flags |= PT_REWIND; + tape->flags |= PT_REWIND; - PT.bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); - if (PT.bufptr == NULL) { - atomic_inc(&PT.available); - printk("%s: buffer allocation failed\n", PT.name); - return -ENOMEM; + err = -ENOMEM; + tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); + if (tape->bufptr == NULL) { + printk("%s: buffer allocation failed\n", tape->name); + goto out; } + file->private_data = tape; return 0; + +out: + atomic_inc(&tape->available); + return err; } static int pt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int unit; + struct pt_unit *tape = file->private_data; struct mtop mtop; - unit = DEVICE_NR(inode); - if (unit >= PT_UNITS) - return -EINVAL; - if (!PT.present) - return -ENODEV; - switch (cmd) { case MTIOCTOP: if (copy_from_user((char *) &mtop, (char *) arg, @@ -730,21 +717,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, switch (mtop.mt_op) { case MTREW: - pt_rewind(unit); + pt_rewind(tape); return 0; case MTWEOF: - pt_write_fm(unit); + pt_write_fm(tape); return 0; default: - printk("%s: Unimplemented mt_op %d\n", PT.name, + printk("%s: Unimplemented mt_op %d\n", tape->name, mtop.mt_op); return -EINVAL; } default: - printk("%s: Unimplemented ioctl 0x%x\n", PT.name, cmd); + printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd); return -EINVAL; } @@ -753,21 +740,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, static int pt_release(struct inode *inode, struct file *file) { - int unit = DEVICE_NR(inode); + struct pt_unit *tape = file->private_data; - if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) + if (atomic_read(&tape->available) > 1) return -EINVAL; - if (PT.flags & PT_WRITING) - pt_write_fm(unit); + if (tape->flags & PT_WRITING) + pt_write_fm(tape); - if (PT.flags & PT_REWIND) - pt_rewind(unit); + if (tape->flags & PT_REWIND) + pt_rewind(tape); - kfree(PT.bufptr); - PT.bufptr = NULL; + kfree(tape->bufptr); + tape->bufptr = NULL; - atomic_inc(&PT.available); + atomic_inc(&tape->available); return 0; @@ -775,70 +762,70 @@ pt_release(struct inode *inode, struct file *file) static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos) { - struct inode *ino = filp->f_dentry->d_inode; - int unit = DEVICE_NR(ino); + struct pt_unit *tape = filp->private_data; + struct pi_adapter *pi = tape->pi; char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, n, r, p, s, t, b; - if (!(PT.flags & (PT_READING | PT_WRITING))) { - PT.flags |= PT_READING; - if (pt_atapi(unit, rd_cmd, 0, NULL, "start read-ahead")) + if (!(tape->flags & (PT_READING | PT_WRITING))) { + tape->flags |= PT_READING; + if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead")) return -EIO; - } else if (PT.flags & PT_WRITING) + } else if (tape->flags & PT_WRITING) return -EIO; - if (PT.flags & PT_EOF) + if (tape->flags & PT_EOF) return 0; t = 0; while (count > 0) { - if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "read")) + if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ - b = (n - 1 + PT.bs) / PT.bs; - n = b * PT.bs; /* rounded up to even block */ + b = (n - 1 + tape->bs) / tape->bs; + n = b * tape->bs; /* rounded up to even block */ rd_cmd[4] = b; - r = pt_command(unit, rd_cmd, n, "read"); + r = pt_command(tape, rd_cmd, n, "read"); mdelay(1); if (r) { - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return -EIO; } while (1) { - r = pt_wait(unit, STAT_BUSY, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_ERR | STAT_READY, DBMSG("read DRQ"), ""); if (r & STAT_SENSE) { - pi_disconnect(PI); - pt_req_sense(unit, 0); + pi_disconnect(pi); + pt_req_sense(tape, 0); return -EIO; } if (r) - PT.flags |= PT_EOF; + tape->flags |= PT_EOF; - s = read_reg(unit, 7); + s = read_reg(pi, 7); if (!(s & STAT_DRQ)) break; - n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); - p = (read_reg(unit, 2) & 3); + n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); + p = (read_reg(pi, 2) & 3); if (p != 2) { - pi_disconnect(PI); - printk("%s: Phase error on read: %d\n", PT.name, + pi_disconnect(pi); + printk("%s: Phase error on read: %d\n", tape->name, p); return -EIO; } @@ -847,13 +834,13 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos k = n; if (k > PT_BUFSIZE) k = PT_BUFSIZE; - pi_read_block(PI, PT.bufptr, k); + pi_read_block(pi, tape->bufptr, k); n -= k; b = k; if (b > count) b = count; - if (copy_to_user(buf + t, PT.bufptr, b)) { - pi_disconnect(PI); + if (copy_to_user(buf + t, tape->bufptr, b)) { + pi_disconnect(pi); return -EFAULT; } t += b; @@ -861,8 +848,8 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos } } - pi_disconnect(PI); - if (PT.flags & PT_EOF) + pi_disconnect(pi); + if (tape->flags & PT_EOF) break; } @@ -872,75 +859,75 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) { - struct inode *ino = filp->f_dentry->d_inode; - int unit = DEVICE_NR(ino); + struct pt_unit *tape = filp->private_data; + struct pi_adapter *pi = tape->pi; char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, n, r, p, s, t, b; - if (!(PT.flags & PT_WRITE_OK)) + if (!(tape->flags & PT_WRITE_OK)) return -EROFS; - if (!(PT.flags & (PT_READING | PT_WRITING))) { - PT.flags |= PT_WRITING; + if (!(tape->flags & (PT_READING | PT_WRITING))) { + tape->flags |= PT_WRITING; if (pt_atapi - (unit, wr_cmd, 0, NULL, "start buffer-available mode")) + (tape, wr_cmd, 0, NULL, "start buffer-available mode")) return -EIO; - } else if (PT.flags & PT_READING) + } else if (tape->flags & PT_READING) return -EIO; - if (PT.flags & PT_EOF) + if (tape->flags & PT_EOF) return -ENOSPC; t = 0; while (count > 0) { - if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "write")) + if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ - b = (n - 1 + PT.bs) / PT.bs; - n = b * PT.bs; /* rounded up to even block */ + b = (n - 1 + tape->bs) / tape->bs; + n = b * tape->bs; /* rounded up to even block */ wr_cmd[4] = b; - r = pt_command(unit, wr_cmd, n, "write"); + r = pt_command(tape, wr_cmd, n, "write"); mdelay(1); if (r) { /* error delivering command only */ - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return -EIO; } while (1) { - r = pt_wait(unit, STAT_BUSY, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_ERR | STAT_READY, DBMSG("write DRQ"), NULL); if (r & STAT_SENSE) { - pi_disconnect(PI); - pt_req_sense(unit, 0); + pi_disconnect(pi); + pt_req_sense(tape, 0); return -EIO; } if (r) - PT.flags |= PT_EOF; + tape->flags |= PT_EOF; - s = read_reg(unit, 7); + s = read_reg(pi, 7); if (!(s & STAT_DRQ)) break; - n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); - p = (read_reg(unit, 2) & 3); + n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); + p = (read_reg(pi, 2) & 3); if (p != 0) { - pi_disconnect(PI); + pi_disconnect(pi); printk("%s: Phase error on write: %d \n", - PT.name, p); + tape->name, p); return -EIO; } @@ -951,19 +938,19 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t b = k; if (b > count) b = count; - if (copy_from_user(PT.bufptr, buf + t, b)) { - pi_disconnect(PI); + if (copy_from_user(tape->bufptr, buf + t, b)) { + pi_disconnect(pi); return -EFAULT; } - pi_write_block(PI, PT.bufptr, k); + pi_write_block(pi, tape->bufptr, k); t += b; count -= b; n -= k; } } - pi_disconnect(PI); - if (PT.flags & PT_EOF) + pi_disconnect(pi); + if (tape->flags & PT_EOF) break; } @@ -977,22 +964,20 @@ static int __init pt_init(void) if (disable) return -1; - pt_init_units(); - if (pt_detect()) return -1; if (register_chrdev(major, name, &pt_fops)) { printk("pt_init: unable to get major number %d\n", major); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) - pi_release(PI); + if (pt[unit].present) + pi_release(pt[unit].pi); return -1; } devfs_mk_dir("pt"); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) { + if (pt[unit].present) { devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, "pt/%d", unit); @@ -1007,15 +992,15 @@ static void __exit pt_exit(void) { int unit; for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) { + if (pt[unit].present) { devfs_remove("pt/%d", unit); devfs_remove("pt/%dn", unit); } devfs_remove("pt"); unregister_chrdev(major, name); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) - pi_release(PI); + if (pt[unit].present) + pi_release(pt[unit].pi); } MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fee64f65341a8ce94e5231628d2f3af1882b9e3b Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:38 -0700 Subject: [PATCH] large dev_t - second series (4/15) cciss cleanup - instead of playing with device numbers, we add helper functions that get host and drive structures by gendisk and use them in open/ioctl/release, same as had been done for cpqarray. --- drivers/block/cciss.c | 222 +++++++++++++++++++++++++------------------------- 1 file changed, 109 insertions(+), 113 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index ce0927b36889..8d2fd57b1b3a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -120,10 +120,10 @@ static int cciss_release(struct inode *inode, struct file *filep); static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -static int revalidate_allvol(kdev_t dev); +static int revalidate_allvol(ctlr_info_t *host); static int cciss_revalidate(struct gendisk *disk); -static int deregister_disk(int ctlr, int logvol); -static int register_new_disk(int cltr); +static int deregister_disk(struct gendisk *disk); +static int register_new_disk(ctlr_info_t *h); static void cciss_getgeometry(int cntl_num); @@ -351,34 +351,42 @@ static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) } } +static inline ctlr_info_t *get_host(struct gendisk *disk) +{ + return disk->queue->queuedata; +} + +static inline drive_info_struct *get_drv(struct gendisk *disk) +{ + return disk->private_data; +} + /* * Open. Make sure the device is really there. */ static int cciss_open(struct inode *inode, struct file *filep) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); + drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk); #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_open %s (%x:%x)\n", inode->i_bdev->bd_disk->disk_name, ctlr, dsk); + printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); #endif /* CCISS_DEBUG */ - if (ctlr >= MAX_CTLR || hba[ctlr] == NULL) - return -ENXIO; /* * Root is allowed to open raw volume zero even if it's not configured * so array config can still work. I don't think I really like this, * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (hba[ctlr]->drv[dsk].nr_blocks == 0) { + if (drv->nr_blocks == 0) { if (iminor(inode) != 0) return -ENXIO; if (!capable(CAP_SYS_ADMIN)) return -EPERM; } - hba[ctlr]->drv[dsk].usage_count++; - hba[ctlr]->usage_count++; + drv->usage_count++; + host->usage_count++; return 0; } /* @@ -386,17 +394,15 @@ static int cciss_open(struct inode *inode, struct file *filep) */ static int cciss_release(struct inode *inode, struct file *filep) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); + drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk); #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_release %s (%x:%x)\n", inode->i_bdev->bd_disk->disk_name, ctlr, dsk); + printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name); #endif /* CCISS_DEBUG */ - /* fsync_dev(inode->i_rdev); */ - - hba[ctlr]->drv[dsk].usage_count--; - hba[ctlr]->usage_count--; + drv->usage_count--; + host->usage_count--; return 0; } @@ -406,8 +412,11 @@ static int cciss_release(struct inode *inode, struct file *filep) static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + ctlr_info_t *host = get_host(disk); + drive_info_struct *drv = get_drv(disk); + int ctlr = host->ctlr; #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg); @@ -417,14 +426,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case HDIO_GETGEO: { struct hd_geometry driver_geo; - if (hba[ctlr]->drv[dsk].cylinders) { - driver_geo.heads = hba[ctlr]->drv[dsk].heads; - driver_geo.sectors = hba[ctlr]->drv[dsk].sectors; - driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders; + if (drv->cylinders) { + driver_geo.heads = drv->heads; + driver_geo.sectors = drv->sectors; + driver_geo.cylinders = drv->cylinders; } else { driver_geo.heads = 0xff; driver_geo.sectors = 0x3f; - driver_geo.cylinders = (int)hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f); + driver_geo.cylinders = (int)drv->nr_blocks / (0xff*0x3f); } driver_geo.start= get_start_sect(inode->i_bdev); if (copy_to_user((void *) arg, &driver_geo, @@ -438,9 +447,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, cciss_pci_info_struct pciinfo; if (!arg) return -EINVAL; - pciinfo.bus = hba[ctlr]->pdev->bus->number; - pciinfo.dev_fn = hba[ctlr]->pdev->devfn; - pciinfo.board_id = hba[ctlr]->board_id; + pciinfo.bus = host->pdev->bus->number; + pciinfo.dev_fn = host->pdev->devfn; + pciinfo.board_id = host->board_id; if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct ))) return -EFAULT; return(0); @@ -448,11 +457,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETINTINFO: { cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; - if (!arg) return -EINVAL; - intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay); - intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount); + intinfo.delay = readl(&host->cfgtable->HostWrite.CoalIntDelay); + intinfo.count = readl(&host->cfgtable->HostWrite.CoalIntCount); if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct ))) return -EFAULT; return(0); @@ -460,7 +467,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_SETINTINFO: { cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; unsigned long flags; int i; @@ -477,13 +483,13 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, spin_lock_irqsave(CCISS_LOCK(ctlr), flags); /* Update the field, and then ring the doorbell */ writel( intinfo.delay, - &(c->cfgtable->HostWrite.CoalIntDelay)); + &(host->cfgtable->HostWrite.CoalIntDelay)); writel( intinfo.count, - &(c->cfgtable->HostWrite.CoalIntCount)); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); + &(host->cfgtable->HostWrite.CoalIntCount)); + writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); for(i=0;ivaddr + SA5_DOORBELL) + if (!(readl(host->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ @@ -497,12 +503,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETNODENAME: { NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; int i; if (!arg) return -EINVAL; for(i=0;i<16;i++) - NodeName[i] = readb(&c->cfgtable->ServerName[i]); + NodeName[i] = readb(&host->cfgtable->ServerName[i]); if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type))) return -EFAULT; return(0); @@ -510,7 +515,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_SETNODENAME: { NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; unsigned long flags; int i; @@ -524,12 +528,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* Update the field, and then ring the doorbell */ for(i=0;i<16;i++) - writeb( NodeName[i], &c->cfgtable->ServerName[i]); + writeb( NodeName[i], &host->cfgtable->ServerName[i]); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); + writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); for(i=0;ivaddr + SA5_DOORBELL) + if (!(readl(host->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ @@ -544,10 +548,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETHEARTBEAT: { Heartbeat_type heartbeat; - ctlr_info_t *c = hba[ctlr]; if (!arg) return -EINVAL; - heartbeat = readl(&c->cfgtable->HeartBeat); + heartbeat = readl(&host->cfgtable->HeartBeat); if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type))) return -EFAULT; return(0); @@ -555,10 +558,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETBUSTYPES: { BusTypes_type BusTypes; - ctlr_info_t *c = hba[ctlr]; if (!arg) return -EINVAL; - BusTypes = readl(&c->cfgtable->BusTypes); + BusTypes = readl(&host->cfgtable->BusTypes); if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) )) return -EFAULT; return(0); @@ -568,7 +570,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, FirmwareVer_type firmware; if (!arg) return -EINVAL; - memcpy(firmware, hba[ctlr]->firm_ver, 4); + memcpy(firmware, host->firm_ver, 4); if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type))) return -EFAULT; @@ -586,12 +588,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, } case CCISS_REVALIDVOLS: - return( revalidate_allvol(inode->i_rdev)); + if (bdev != bdev->bd_contains || drv != host->drv) + return -ENXIO; + return revalidate_allvol(host); case CCISS_GETLUNINFO: { LogvolInfo_struct luninfo; - struct gendisk *disk = hba[ctlr]->gendisk[dsk]; - drive_info_struct *drv = &hba[ctlr]->drv[dsk]; int i; luninfo.LunID = drv->LunID; @@ -610,16 +612,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, return(0); } case CCISS_DEREGDISK: - return( deregister_disk(ctlr,dsk)); + return deregister_disk(disk); case CCISS_REGNEWD: - { - return(register_new_disk(ctlr)); - } + return register_new_disk(host); + case CCISS_PASSTHRU: { IOCTL_Command_struct iocommand; - ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; char *buff = NULL; u64bit temp64; @@ -655,7 +655,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, return -EFAULT; } } - if ((c = cmd_alloc(h , 0)) == NULL) + if ((c = cmd_alloc(host , 0)) == NULL) { kfree(buff); return -ENOMEM; @@ -682,7 +682,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, // Fill in the scatter gather information if (iocommand.buf_size > 0 ) { - temp64.val = pci_map_single( h->pdev, buff, + temp64.val = pci_map_single( host->pdev, buff, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); c->SG[0].Addr.lower = temp64.val32.lower; @@ -694,9 +694,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* Put the request on the tail of the request queue */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); wait_for_completion(&wait); @@ -704,7 +704,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* unlock the buffers from DMA */ temp64.val32.lower = c->SG[0].Addr.lower; temp64.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, + pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); /* Copy the error information out */ @@ -712,7 +712,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) ) { kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return( -EFAULT); } @@ -722,17 +722,16 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) { kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return -EFAULT; } } kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return(0); } case CCISS_BIG_PASSTHRU: { BIG_IOCTL_Command_struct *ioc; - ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; unsigned char **buff = NULL; int *buff_size = NULL; @@ -798,7 +797,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, data_ptr += sz; sg_used++; } - if ((c = cmd_alloc(h , 0)) == NULL) { + if ((c = cmd_alloc(host , 0)) == NULL) { status = -ENOMEM; goto cleanup1; } @@ -819,7 +818,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if (ioc->buf_size > 0 ) { int i; for(i=0; ipdev, buff[i], + temp64.val = pci_map_single( host->pdev, buff[i], buff_size[i], PCI_DMA_BIDIRECTIONAL); c->SG[i].Addr.lower = temp64.val32.lower; @@ -831,22 +830,22 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, c->waiting = &wait; /* Put the request on the tail of the request queue */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); wait_for_completion(&wait); /* unlock the buffers from DMA */ for(i=0; iSG[i].Addr.lower; temp64.val32.upper = c->SG[i].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, + pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, buff_size[i], PCI_DMA_BIDIRECTIONAL); } /* Copy the error information out */ ioc->error_info = *(c->err_info); if (copy_to_user((void *) arg, ioc, sizeof(*ioc))) { - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = -EFAULT; goto cleanup1; } @@ -855,14 +854,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, BYTE *ptr = (BYTE *) ioc->buf; for(i=0; i< sg_used; i++) { if (copy_to_user(ptr, buff[i], buff_size[i])) { - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = -EFAULT; goto cleanup1; } ptr += buff_size[i]; } } - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = 0; cleanup1: if (buff) { @@ -901,27 +900,23 @@ static int cciss_revalidate(struct gendisk *disk) * particualar logical volume (instead of all of them on a particular * controller). */ -static int revalidate_allvol(kdev_t dev) +static int revalidate_allvol(ctlr_info_t *host) { - int ctlr, i; + int ctlr = host->ctlr, i; unsigned long flags; - ctlr = major(dev) - COMPAQ_CISS_MAJOR; - if (minor(dev) != 0) - return -ENXIO; - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - if (hba[ctlr]->usage_count > 1) { + if (host->usage_count > 1) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); printk(KERN_WARNING "cciss: Device busy for volume" - " revalidation (usage=%d)\n", hba[ctlr]->usage_count); + " revalidation (usage=%d)\n", host->usage_count); return -EBUSY; } - hba[ctlr]->usage_count++; + host->usage_count++; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); for(i=0; i< NWD; i++) { - struct gendisk *disk = hba[ctlr]->gendisk[i]; + struct gendisk *disk = host->gendisk[i]; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); } @@ -930,54 +925,55 @@ static int revalidate_allvol(kdev_t dev) * Set the partition and block size structures for all volumes * on this controller to zero. We will reread all of this data */ - memset(hba[ctlr]->drv, 0, sizeof(drive_info_struct) + memset(host->drv, 0, sizeof(drive_info_struct) * CISS_MAX_LUN); /* * Tell the array controller not to give us any interrupts while * we check the new geometry. Then turn interrupts back on when * we're done. */ - hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_OFF); + host->access.set_intr_mask(host, CCISS_INTR_OFF); cciss_getgeometry(ctlr); - hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON); + host->access.set_intr_mask(host, CCISS_INTR_ON); /* Loop through each real device */ for (i = 0; i < NWD; i++) { - struct gendisk *disk = hba[ctlr]->gendisk[i]; - drive_info_struct *drv = &(hba[ctlr]->drv[i]); + struct gendisk *disk = host->gendisk[i]; + drive_info_struct *drv = &(host->drv[i]); if (!drv->nr_blocks) continue; - blk_queue_hardsect_size(hba[ctlr]->queue, drv->block_size); + blk_queue_hardsect_size(host->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); } - hba[ctlr]->usage_count--; + host->usage_count--; return 0; } -static int deregister_disk(int ctlr, int logvol) +static int deregister_disk(struct gendisk *disk) { unsigned long flags; - struct gendisk *disk = hba[ctlr]->gendisk[logvol]; - ctlr_info_t *h = hba[ctlr]; + ctlr_info_t *h = get_host(disk); + drive_info_struct *drv = get_drv(disk); + int ctlr = h->ctlr; if (!capable(CAP_SYS_RAWIO)) return -EPERM; spin_lock_irqsave(CCISS_LOCK(ctlr), flags); /* make sure logical volume is NOT is use */ - if( h->drv[logvol].usage_count > 1) { + if( drv->usage_count > 1) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); return -EBUSY; } - h->drv[logvol].usage_count++; + drv->usage_count++; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); /* invalidate the devices and deregister the disk */ if (disk->flags & GENHD_FL_UP) del_gendisk(disk); /* check to see if it was the last disk */ - if (logvol == h->highest_lun) { + if (drv == h->drv + h->highest_lun) { /* if so, find the new hightest lun */ int i, newhighest =-1; for(i=0; ihighest_lun; i++) { @@ -990,10 +986,10 @@ static int deregister_disk(int ctlr, int logvol) } --h->num_luns; /* zero out the disk size info */ - h->drv[logvol].nr_blocks = 0; - h->drv[logvol].block_size = 0; - h->drv[logvol].cylinders = 0; - h->drv[logvol].LunID = 0; + drv->nr_blocks = 0; + drv->block_size = 0; + drv->cylinders = 0; + drv->LunID = 0; return(0); } static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, @@ -1304,10 +1300,10 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, *total_size, *block_size); return; } -static int register_new_disk(int ctlr) +static int register_new_disk(ctlr_info_t *h) { struct gendisk *disk; - ctlr_info_t *h = hba[ctlr]; + int ctlr = h->ctlr; int i; int num_luns; int logvol; @@ -1417,7 +1413,7 @@ static int register_new_disk(int ctlr) #ifdef CCISS_DEBUG printk("Checking Index %d\n", i); #endif /* CCISS_DEBUG */ - if(hba[ctlr]->drv[i].LunID == 0) + if(h->drv[i].LunID == 0) { #ifdef CCISS_DEBUG printk("free index found at %d\n", i); @@ -1434,19 +1430,19 @@ static int register_new_disk(int ctlr) } logvol = free_index; - hba[ctlr]->drv[logvol].LunID = lunid; + h->drv[logvol].LunID = lunid; /* there could be gaps in lun numbers, track hightest */ - if(hba[ctlr]->highest_lun < lunid) - hba[ctlr]->highest_lun = logvol; + if(h->highest_lun < lunid) + h->highest_lun = logvol; cciss_read_capacity(ctlr, logvol, size_buff, 1, &total_size, &block_size); cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, - inq_buff, &hba[ctlr]->drv[logvol]); - hba[ctlr]->drv[logvol].usage_count = 0; - ++hba[ctlr]->num_luns; + inq_buff, &h->drv[logvol]); + h->drv[logvol].usage_count = 0; + ++h->num_luns; /* setup partitions per disk */ - disk = hba[ctlr]->gendisk[logvol]; - set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks); + disk = h->gendisk[logvol]; + set_capacity(disk, h->drv[logvol].nr_blocks); add_disk(disk); freeret: kfree(ld_buff); -- cgit v1.2.3 From 25a6ca892403f9d5dc2e1ed28db13e31b9fea2d2 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:47 -0700 Subject: [PATCH] large dev_t - second series (5/15) cdevname() killed, there was only one remaining user (tty_paranoia_check()) and in that case cdevname() was worse than plain major:minor (basically, it's "you've got corrupted inode that was supposed to belong to tty device; here's what I'd found in ->i_rdev") --- drivers/char/tty_io.c | 13 ++++++------- fs/char_dev.c | 21 --------------------- include/linux/fs.h | 1 - kernel/ksyms.c | 1 - 4 files changed, 6 insertions(+), 30 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 5b4693c5f990..83640a923209 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -181,17 +181,16 @@ inline int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, const char *routine) { #ifdef TTY_PARANOIA_CHECK - static const char badmagic[] = KERN_WARNING - "Warning: bad magic number for tty struct (%s) in %s\n"; - static const char badtty[] = KERN_WARNING - "Warning: null TTY for (%s) in %s\n"; - if (!tty) { - printk(badtty, cdevname(inode->i_rdev), routine); + printk(KERN_WARNING + "null TTY for (%d:%d) in %s\n", + imajor(inode), iminor(inode), routine); return 1; } if (tty->magic != TTY_MAGIC) { - printk(badmagic, cdevname(inode->i_rdev), routine); + printk(KERN_WARNING + "bad magic number for tty struct (%d:%d) in %s\n", + imajor(inode), iminor(inode), routine); return 1; } #endif diff --git a/fs/char_dev.c b/fs/char_dev.c index 3c6258c73384..e41bf7caa5ee 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -328,27 +328,6 @@ struct file_operations def_chr_fops = { .open = chrdev_open, }; -const char *cdevname(kdev_t dev) -{ - static char buffer[40]; - const char *name = "unknown-char"; - unsigned int major = major(dev); - unsigned int minor = minor(dev); - int i = major_to_index(major); - struct char_device_struct *cd; - - read_lock(&chrdevs_lock); - for (cd = chrdevs[i]; cd; cd = cd->next) - if (cd->major == major) - break; - if (cd) - name = cd->name; - sprintf(buffer, "%s(%d,%d)", name, major, minor); - read_unlock(&chrdevs_lock); - - return buffer; -} - static struct kobject *exact_match(dev_t dev, int *part, void *data) { struct cdev *p = data; diff --git a/include/linux/fs.h b/include/linux/fs.h index 87ae270bf96c..fa2bd2dd7600 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1156,7 +1156,6 @@ extern struct block_device *lookup_bdev(const char *); extern struct block_device *open_bdev_excl(const char *, int, int, void *); extern void close_bdev_excl(struct block_device *, int); -extern const char * cdevname(kdev_t); extern void init_special_inode(struct inode *, umode_t, dev_t); /* Invalid inode operations -- fs/bad_inode.c */ diff --git a/kernel/ksyms.c b/kernel/ksyms.c index e503bd8b0349..9f61a0496c2a 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -511,7 +511,6 @@ EXPORT_SYMBOL(vsnprintf); EXPORT_SYMBOL(vsscanf); EXPORT_SYMBOL(__bdevname); EXPORT_SYMBOL(bdevname); -EXPORT_SYMBOL(cdevname); EXPORT_SYMBOL(simple_strtoull); EXPORT_SYMBOL(simple_strtoul); EXPORT_SYMBOL(simple_strtol); -- cgit v1.2.3 From cbac67b10e48a7a76485d405fc723084fdafb6a1 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:53:56 -0700 Subject: [PATCH] large dev_t - second series (6/15) tty redirect handling sanitized. Such ttys (/dev/tty and /dev/console) get a different file_operations; its ->write() handles redirects; checks for file->f_op == &tty_fops updated, checks for major:minor being that of a redirector replaced with check for ->f_op->write value. Piece of code in tty_io.c that had been #if 0 since 0.99 had been finally put out of its misery. kdev_val() is gone. --- drivers/char/n_tty.c | 13 ++--- drivers/char/tty_io.c | 126 ++++++++++++++++++++++--------------------------- include/linux/kdev_t.h | 10 ---- 3 files changed, 61 insertions(+), 88 deletions(-) diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 883066efbd72..6cc938bbbf30 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -50,9 +50,6 @@ #include #include -#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0)) -#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1)) - /* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 @@ -951,6 +948,8 @@ static inline int copy_from_read_buf(struct tty_struct *tty, return retval; } +extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *); + static ssize_t read_chan(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t nr) { @@ -975,9 +974,7 @@ do_it_again: /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (!IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) && - !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev) && - current->tty == tty) { + if (file->f_op->write != redirected_tty_write && current->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); else if (current->pgrp != tty->pgrp) { @@ -1168,9 +1165,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ - if (L_TOSTOP(tty) && - !IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) && - !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev)) { + if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 83640a923209..a1888c4dc0d9 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -103,11 +103,6 @@ #include -#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0)) -#define IS_TTY_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0)) -#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1)) -#define IS_PTMX_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2)) - #undef TTY_DEBUG_HANGUP #define TTY_PARANOIA_CHECK 1 @@ -136,6 +131,7 @@ static void initialize_tty_struct(struct tty_struct *tty); static ssize_t tty_read(struct file *, char *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char *, size_t, loff_t *); +ssize_t redirected_tty_write(struct file *, const char *, size_t, loff_t *); static unsigned int tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); @@ -382,6 +378,17 @@ static struct file_operations tty_fops = { .fasync = tty_fasync, }; +static struct file_operations console_fops = { + .llseek = no_llseek, + .read = tty_read, + .write = redirected_tty_write, + .poll = tty_poll, + .ioctl = tty_ioctl, + .open = tty_open, + .release = tty_release, + .fasync = tty_fasync, +}; + static struct file_operations hung_up_tty_fops = { .llseek = no_llseek, .read = hung_up_tty_read, @@ -425,12 +432,9 @@ void do_tty_hangup(void *data) check_tty_count(tty, "do_tty_hangup"); file_list_lock(); list_for_each_entry(filp, &tty->tty_files, f_list) { - if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) || - IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) { + if (filp->f_op->write == redirected_tty_write) cons_filp = filp; - continue; - } - if (filp->f_op != &tty_fops) + if (filp->f_op->write != tty_write) continue; closecount++; tty_fasync(-1, filp, 0); /* can't block */ @@ -650,22 +654,6 @@ static ssize_t tty_read(struct file * file, char * buf, size_t count, if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) return -EIO; - /* This check not only needs to be done before reading, but also - whenever read_chan() gets woken up after sleeping, so I've - moved it to there. This should only be done for the N_TTY - line discipline, anyway. Same goes for write_chan(). -- jlc. */ -#if 0 - if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */ - (tty->pgrp > 0) && - (current->tty == tty) && - (tty->pgrp != current->pgrp)) - if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp)) - return -EIO; - else { - (void) kill_pg(current->pgrp, SIGTTIN, 1); - return -ERESTARTSYS; - } -#endif lock_kernel(); if (tty->ldisc.read) i = (tty->ldisc.read)(tty,file,buf,count); @@ -730,37 +718,13 @@ static inline ssize_t do_tty_write( static ssize_t tty_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { - int is_console; struct tty_struct * tty; struct inode *inode = file->f_dentry->d_inode; - /* - * For now, we redirect writes from /dev/console as - * well as /dev/tty0. - */ - is_console = IS_SYSCONS_DEV(inode->i_rdev) || - IS_CONSOLE_DEV(inode->i_rdev); /* Can't seek (pwrite) on ttys. */ if (ppos != &file->f_pos) return -ESPIPE; - if (is_console) { - struct file *p = NULL; - - spin_lock(&redirect_lock); - if (redirect) { - get_file(redirect); - p = redirect; - } - spin_unlock(&redirect_lock); - - if (p) { - ssize_t res = vfs_write(p, buf, count, &p->f_pos); - fput(p); - return res; - } - } - tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; @@ -772,6 +736,31 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count, (const unsigned char *)buf, count); } +ssize_t redirected_tty_write(struct file * file, const char * buf, size_t count, + loff_t *ppos) +{ + struct file *p = NULL; + + spin_lock(&redirect_lock); + if (redirect) { + get_file(redirect); + p = redirect; + } + spin_unlock(&redirect_lock); + + if (p) { + ssize_t res; + /* Can't seek (pwrite) on ttys. */ + if (ppos != &file->f_pos) + return -ESPIPE; + res = vfs_write(p, buf, count, &p->f_pos); + fput(p); + return res; + } + + return tty_write(file, buf, count, ppos); +} + /* Semaphore to protect creating and releasing a tty */ static DECLARE_MUTEX(tty_sem); @@ -1306,14 +1295,11 @@ static int tty_open(struct inode * inode, struct file * filp) int noctty, retval; struct tty_driver *driver; int index; - kdev_t device; - unsigned short saved_flags; - - saved_flags = filp->f_flags; + dev_t device = kdev_t_to_nr(inode->i_rdev); + unsigned short saved_flags = filp->f_flags; retry_open: noctty = filp->f_flags & O_NOCTTY; - device = inode->i_rdev; - if (IS_TTY_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->tty) return -ENXIO; driver = current->tty->driver; @@ -1323,7 +1309,7 @@ retry_open: goto got_driver; } #ifdef CONFIG_VT - if (IS_CONSOLE_DEV(device)) { + if (device == MKDEV(TTY_MAJOR,0)) { extern int fg_console; extern struct tty_driver *console_driver; driver = console_driver; @@ -1332,7 +1318,7 @@ retry_open: goto got_driver; } #endif - if (IS_SYSCONS_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,1)) { struct console *c = console_drivers; for (c = console_drivers; c; c = c->next) { if (!c->device) @@ -1348,7 +1334,7 @@ retry_open: return -ENODEV; } - if (IS_PTMX_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,2)) { #ifdef CONFIG_UNIX98_PTYS /* find a device that is not in use. */ retval = -1; @@ -1365,7 +1351,7 @@ retry_open: return -ENODEV; #endif /* CONFIG_UNIX_98_PTYS */ } else { - driver = get_tty_driver(kdev_t_to_nr(device), &index); + driver = get_tty_driver(device, &index); if (!driver) return -ENODEV; got_driver: @@ -1407,7 +1393,8 @@ got_driver: /* * Need to reset f_op in case a hangup happened. */ - filp->f_op = &tty_fops; + if (filp->f_op == &hung_up_tty_fops) + filp->f_op = &tty_fops; goto retry_open; } if (!noctty && @@ -1516,10 +1503,9 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, return 0; } -static int tioccons(struct inode *inode, struct file *file) +static int tioccons(struct file *file) { - if (IS_SYSCONS_DEV(inode->i_rdev) || - IS_CONSOLE_DEV(inode->i_rdev)) { + if (file->f_op->write == redirected_tty_write) { struct file *f; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1786,7 +1772,7 @@ int tty_ioctl(struct inode * inode, struct file * file, case TIOCSWINSZ: return tiocswinsz(tty, real_tty, (struct winsize *) arg); case TIOCCONS: - return real_tty!=tty ? -EINVAL : tioccons(inode, file); + return real_tty!=tty ? -EINVAL : tioccons(file); case FIONBIO: return fionbio(file, (int *) arg); case TIOCEXCL: @@ -1917,8 +1903,10 @@ static void __do_SAK(void *arg) spin_lock(&p->files->file_lock); for (i=0; i < p->files->max_fds; i++) { filp = fcheck_files(p->files, i); - if (filp && (filp->f_op == &tty_fops) && - (filp->private_data == tty)) { + if (!filp) + continue; + if (filp->f_op->read == tty_read && + filp->private_data == tty) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", p->pid, p->comm, i); @@ -2446,7 +2434,7 @@ void __init tty_init(void) tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL); strcpy(console_cdev.kobj.name, "dev.console"); - cdev_init(&console_cdev, &tty_fops); + cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); @@ -2468,7 +2456,7 @@ void __init tty_init(void) #ifdef CONFIG_VT strcpy(vc0_cdev.kobj.name, "dev.vc0"); - cdev_init(&vc0_cdev, &tty_fops); + cdev_init(&vc0_cdev, &console_fops); if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) panic("Couldn't register /dev/tty0 driver\n"); diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h index 900a4a1e1282..64a88b3b194a 100644 --- a/include/linux/kdev_t.h +++ b/include/linux/kdev_t.h @@ -80,16 +80,6 @@ typedef struct { #define mk_kdev(major, minor) ((kdev_t) { __mkdev(major,minor) } ) -/* - * The "values" are just _cookies_, usable for - * internal equality comparisons and for things - * like NFS filehandle conversion. - */ -static inline unsigned int kdev_val(kdev_t dev) -{ - return dev.value; -} - #define NODEV (mk_kdev(0,0)) /* Mask off the high bits for now.. */ -- cgit v1.2.3 From ad1da81a8a2acf7ceda4e8aa67e159ff223dc337 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:08 -0700 Subject: [PATCH] large dev_t - second series (7/15) the last kdev_t object is gone; ->i_rdev switched to dev_t. --- drivers/char/tty_io.c | 2 +- drivers/md/dm-table.c | 2 +- fs/block_dev.c | 4 ++-- fs/char_dev.c | 2 +- fs/cifs/file.c | 4 ++-- fs/cifs/inode.c | 4 ++-- fs/devfs/base.c | 4 ++-- fs/ext2/inode.c | 2 +- fs/ext3/inode.c | 2 +- fs/hpfs/inode.c | 2 +- fs/inode.c | 6 +++--- fs/intermezzo/vfs.c | 2 +- fs/isofs/inode.c | 3 +-- fs/isofs/rock.c | 4 ++-- fs/jffs2/super.c | 6 +++--- fs/jfs/inode.c | 3 +-- fs/jfs/jfs_imap.c | 4 ++-- fs/minix/inode.c | 4 ++-- fs/nfsd/nfsproc.c | 4 ++-- fs/reiserfs/inode.c | 4 ++-- fs/stat.c | 2 +- fs/sysv/inode.c | 2 +- fs/udf/inode.c | 4 ++-- fs/ufs/inode.c | 2 +- fs/xfs/linux/xfs_iops.c | 2 +- fs/xfs/linux/xfs_super.c | 4 ++-- fs/xfs/xfs_types.h | 2 +- fs/xfs/xfsidbg.c | 2 +- include/linux/fs.h | 6 +++--- 29 files changed, 46 insertions(+), 48 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a1888c4dc0d9..8d1f8c6d3c23 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1295,7 +1295,7 @@ static int tty_open(struct inode * inode, struct file * filp) int noctty, retval; struct tty_driver *driver; int index; - dev_t device = kdev_t_to_nr(inode->i_rdev); + dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; retry_open: noctty = filp->f_flags & O_NOCTTY; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5d0e4c662599..aae61522d1f7 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -312,7 +312,7 @@ static int lookup_device(const char *path, dev_t *dev) goto out; } - *dev = kdev_t_to_nr(inode->i_rdev); + *dev = inode->i_rdev; out: path_release(&nd); diff --git a/fs/block_dev.c b/fs/block_dev.c index ddfcb6284b5a..e08095251aab 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -345,7 +345,7 @@ struct block_device *bdget(dev_t dev) bdev->bd_part_count = 0; bdev->bd_invalidated = 0; inode->i_mode = S_IFBLK; - inode->i_rdev = to_kdev_t(dev); + inode->i_rdev = dev; inode->i_bdev = bdev; inode->i_data.a_ops = &def_blk_aops; mapping_set_gfp_mask(&inode->i_data, GFP_USER); @@ -386,7 +386,7 @@ int bd_acquire(struct inode *inode) return 0; } spin_unlock(&bdev_lock); - bdev = bdget(kdev_t_to_nr(inode->i_rdev)); + bdev = bdget(inode->i_rdev); if (!bdev) return -ENOMEM; spin_lock(&bdev_lock); diff --git a/fs/char_dev.c b/fs/char_dev.c index e41bf7caa5ee..44303f85e624 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -265,7 +265,7 @@ int chrdev_open(struct inode * inode, struct file * filp) struct kobject *kobj; int idx; spin_unlock(&cdev_lock); - kobj = kobj_lookup(cdev_map, kdev_t_to_nr(inode->i_rdev), &idx); + kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); if (!kobj) return -ENODEV; new = container_of(kobj, struct cdev, kobj); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 247a39b899b3..5e223961e9fb 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1024,7 +1024,7 @@ fill_in_inode(struct inode *tmp_inode, } else { cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, - kdev_t_to_nr(tmp_inode->i_rdev)); + tmp_inode->i_rdev); } } @@ -1094,7 +1094,7 @@ unix_fill_in_inode(struct inode *tmp_inode, } else { cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, - kdev_t_to_nr(tmp_inode->i_rdev)); + tmp_inode->i_rdev); } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3625916ca351..6524d6d1f883 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -154,7 +154,7 @@ cifs_get_inode_info_unix(struct inode **pinode, } else { cFYI(1, (" Init special inode ")); init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } FreeXid(xid); @@ -298,7 +298,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, inode->i_op = &cifs_symlink_inode_ops; } else { init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } if(buf) diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 3df3c5dc1697..fda21d6af987 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2012,11 +2012,11 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb, inode->i_fop = &devfs_fops; if ( S_ISCHR (de->mode) ) { - inode->i_rdev = to_kdev_t(de->u.cdev.dev); + inode->i_rdev = de->u.cdev.dev; } else if ( S_ISBLK (de->mode) ) { - inode->i_rdev = to_kdev_t(de->u.bdev.dev); + inode->i_rdev = de->u.bdev.dev; if (bd_acquire (inode) != 0) PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino); } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 8a009a159469..c9d6cf4a3869 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1216,7 +1216,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); + raw_inode->i_block[0] = cpu_to_le32(inode->i_rdev); else for (n = 0; n < EXT2_N_BLOCKS; n++) raw_inode->i_block[n] = ei->i_data[n]; mark_buffer_dirty(bh); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 84f41589a02a..24bd9d1fc7de 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2668,7 +2668,7 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = - cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); + cpu_to_le32(inode->i_rdev); else for (block = 0; block < EXT3_N_BLOCKS; block++) raw_inode->i_block[block] = ei->i_data[block]; diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 2d4042ac2ae0..94293028a9ec 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -225,7 +225,7 @@ void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) hpfs_inode->i_ea_mode = 1; } if (S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode)) { - int d = kdev_t_to_nr(i->i_rdev); + dev_t d = i->i_rdev; ea[0] = d & 0xff; ea[1] = (d >> 8) & 0xff; ea[2] = (d >> 16) & 0xff; diff --git a/fs/inode.c b/fs/inode.c index bd116dc1fadc..df29026f21c1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -130,7 +130,7 @@ static struct inode *alloc_inode(struct super_block *sb) inode->i_pipe = NULL; inode->i_bdev = NULL; inode->i_cdev = NULL; - inode->i_rdev = to_kdev_t(0); + inode->i_rdev = 0; inode->i_security = NULL; if (security_inode_alloc(inode)) { if (inode->i_sb->s_op->destroy_inode) @@ -1363,10 +1363,10 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) inode->i_mode = mode; if (S_ISCHR(mode)) { inode->i_fop = &def_chr_fops; - inode->i_rdev = to_kdev_t(rdev); + inode->i_rdev = rdev; } else if (S_ISBLK(mode)) { inode->i_fop = &def_blk_fops; - inode->i_rdev = to_kdev_t(rdev); + inode->i_rdev = rdev; } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c index 920ba2773961..469a463c8752 100644 --- a/fs/intermezzo/vfs.c +++ b/fs/intermezzo/vfs.c @@ -290,7 +290,7 @@ int presto_settime(struct presto_file_set *fset, void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb) { rb->rb_mode = (__u32)inode->i_mode; - rb->rb_rdev = (__u32)kdev_t_to_nr(inode->i_rdev); + rb->rb_rdev = (__u32)inode->i_rdev; rb->rb_uid = (__u64)inode->i_uid; rb->rb_gid = (__u64)inode->i_gid; } diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index a28d5f174b9b..bbff5798e2d3 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1329,8 +1329,7 @@ static void isofs_read_inode(struct inode * inode) inode->i_data.a_ops = &isofs_symlink_aops; } else /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + init_special_inode(inode, inode->i_mode, inode->i_rdev); out: if (tmpde) diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 8d66d202f04e..ec218349feb1 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -228,9 +228,9 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { - inode->i_rdev = mk_kdev(low >> 8, low & 0xff); + inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { - inode->i_rdev = mk_kdev(high, low); + inode->i_rdev = MKDEV(high, low); } } break; diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 8bc53c400875..991dcaf15c72 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -174,7 +174,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, int err; struct nameidata nd; int mtdnr; - kdev_t dev; + dev_t dev; if (!dev_name) return ERR_PTR(-EINVAL); @@ -240,14 +240,14 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, dev = nd.dentry->d_inode->i_rdev; path_release(&nd); - if (major(dev) != MTD_BLOCK_MAJOR) { + if (MAJOR(dev) != MTD_BLOCK_MAJOR) { if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", dev_name); return ERR_PTR(-EINVAL); } - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, minor(dev)); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, MINOR(dev)); } diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 4ad780e83e73..989621a380b6 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -61,8 +61,7 @@ void jfs_read_inode(struct inode *inode) inode->i_op = &jfs_symlink_inode_operations; } else { inode->i_op = &jfs_file_inode_operations; - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + init_special_inode(inode, inode->i_mode, inode->i_rdev); } } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 847afd3030d8..7ee8f04862cc 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -3043,7 +3043,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) jfs_ip->acltype = le32_to_cpu(dip->di_acltype); if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - ip->i_rdev = to_kdev_t(le32_to_cpu(dip->di_rdev)); + ip->i_rdev = le32_to_cpu(dip->di_rdev); if (S_ISDIR(ip->i_mode)) { memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384); @@ -3102,7 +3102,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip) dip->di_acltype = cpu_to_le32(jfs_ip->acltype); if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - dip->di_rdev = cpu_to_le32(kdev_t_to_nr(ip->i_rdev)); + dip->di_rdev = cpu_to_le32(ip->i_rdev); } #ifdef _JFS_DEBUG_IMAP diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 710e46886609..1c98d1103729 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -460,7 +460,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode) raw_inode->i_size = inode->i_size; raw_inode->i_time = inode->i_mtime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); + raw_inode->i_zone[0] = inode->i_rdev; else for (i = 0; i < 9; i++) raw_inode->i_zone[i] = minix_inode->u.i1_data[i]; mark_buffer_dirty(bh); @@ -489,7 +489,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode) raw_inode->i_atime = inode->i_atime.tv_sec; raw_inode->i_ctime = inode->i_ctime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); + raw_inode->i_zone[0] = inode->i_rdev; else for (i = 0; i < 10; i++) raw_inode->i_zone[i] = minix_inode->u.i2_data[i]; mark_buffer_dirty(bh); diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index b41f63972df7..d0dda80f9c47 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -242,7 +242,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, case S_IFCHR: case S_IFBLK: /* reserve rdev for later checking */ - attr->ia_size = kdev_t_to_nr(inode->i_rdev); + attr->ia_size = inode->i_rdev; attr->ia_valid |= ATTR_SIZE; /* FALLTHROUGH */ @@ -300,7 +300,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, /* Make sure the type and device matches */ nfserr = nfserr_exist; if (inode && (type != (inode->i_mode & S_IFMT) || - (is_borc && kdev_t_to_nr(inode->i_rdev) != rdev))) + (is_borc && inode->i_rdev != rdev))) goto out_unlock; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 3f621de0ba22..d18538e49f21 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1024,7 +1024,7 @@ static void inode2sd (void * sd, struct inode * inode) set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec ); set_sd_v2_blocks(sd_v2, inode->i_blocks ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) ); + set_sd_v2_rdev(sd_v2, inode->i_rdev); else set_sd_v2_generation(sd_v2, inode->i_generation); flags = REISERFS_I(inode)->i_attrs; @@ -1048,7 +1048,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode) set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v1_rdev(sd_v1, kdev_t_to_nr(inode->i_rdev) ); + set_sd_v1_rdev(sd_v1, inode->i_rdev); else set_sd_v1_blocks(sd_v1, inode->i_blocks ); diff --git a/fs/stat.c b/fs/stat.c index 7f034fa65d88..a1f3d7d874fa 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -24,7 +24,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; - stat->rdev = kdev_t_to_nr(inode->i_rdev); + stat->rdev = inode->i_rdev; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; stat->ctime = inode->i_ctime; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 9a4564610aae..60fca2128567 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -241,7 +241,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) si = SYSV_I(inode); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - si->i_data[0] = cpu_to_fs32(sbi, kdev_t_to_nr(inode->i_rdev)); + si->i_data[0] = cpu_to_fs32(sbi, inode->i_rdev); for (block = 0; block < 10+1+1+1; block++) write3byte(sbi, (u8 *)&si->i_data[block], &raw_inode->i_data[3*block]); diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2fa65ab370d7..1c2fba3d5655 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1392,8 +1392,8 @@ udf_update_inode(struct inode *inode, int do_sync) strcpy(eid->ident, UDF_ID_DEVELOPER); eid->identSuffix[0] = UDF_OS_CLASS_UNIX; eid->identSuffix[1] = UDF_OS_ID_LINUX; - dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8; - dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF; + dsea->majorDeviceIdent = inode->i_rdev >> 8; + dsea->minorDeviceIdent = inode->i_rdev & 0xFF; mark_buffer_dirty_inode(tbh, inode); udf_release_data(tbh); } diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 442c28e17739..f8c113bd3677 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -619,7 +619,7 @@ static int ufs_update_inode(struct inode * inode, int do_sync) } if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev)); + ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); else if (inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; diff --git a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c index 11eac5784afa..5f316085b1b9 100644 --- a/fs/xfs/linux/xfs_iops.c +++ b/fs/xfs/linux/xfs_iops.c @@ -178,7 +178,7 @@ linvfs_mknod( ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) - ip->i_rdev = to_kdev_t(rdev); + ip->i_rdev = rdev; else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c index 49c173f9e5d0..1bd4b3a4a604 100644 --- a/fs/xfs/linux/xfs_super.c +++ b/fs/xfs/linux/xfs_super.c @@ -154,7 +154,7 @@ xfs_set_inodeops( } else { inode->i_op = &linvfs_file_inode_operations; init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } @@ -171,7 +171,7 @@ xfs_revalidate_inode( inode->i_uid = ip->i_d.di_uid; inode->i_gid = ip->i_d.di_gid; if (((1 << vp->v_type) & ((1<i_rdev = NODEV; + inode->i_rdev = 0; } else { xfs_dev_t dev = ip->i_df.if_u2.if_rdev; inode->i_rdev = XFS_DEV_TO_KDEVT(dev); diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index bdb7ca141927..3c163b46160e 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h @@ -210,6 +210,6 @@ typedef enum { #define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<i_mode, ip->i_nlink, - kdev_t_to_nr(ip->i_rdev), ip->i_state); + ip->i_rdev, ip->i_state); kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n", ip->i_hash.next, ip->i_hash.prev); diff --git a/include/linux/fs.h b/include/linux/fs.h index fa2bd2dd7600..fe2bfd295802 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -373,7 +373,7 @@ struct inode { unsigned int i_nlink; uid_t i_uid; gid_t i_gid; - kdev_t i_rdev; + dev_t i_rdev; loff_t i_size; struct timespec i_atime; struct timespec i_mtime; @@ -469,12 +469,12 @@ static inline void i_size_write(struct inode *inode, loff_t i_size) static inline unsigned iminor(struct inode *inode) { - return minor(inode->i_rdev); + return MINOR(inode->i_rdev); } static inline unsigned imajor(struct inode *inode) { - return major(inode->i_rdev); + return MAJOR(inode->i_rdev); } struct fown_struct { -- cgit v1.2.3 From 5900b09861dd856ca475dd444793ff6c671acc84 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:18 -0700 Subject: [PATCH] large dev_t - second series (8/15) kdev_t, to_kdev_t(), etc. are gone - there is no more objects of that type and no remaining callers of these functions. --- drivers/s390/char/tape_core.c | 2 +- drivers/s390/char/tape_proc.c | 2 +- drivers/scsi/sg.c | 2 +- drivers/scsi/sr.c | 2 +- include/linux/kdev_t.h | 99 ------------------------------------------- net/unix/af_unix.c | 2 +- 6 files changed, 5 insertions(+), 104 deletions(-) diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 7656f1eddc6e..48fb7e002944 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -178,7 +178,7 @@ tape_assign_minor(struct tape_device *device) break; minor += TAPE_MINORS_PER_DEV; } - if (minor >= (1 << KDEV_MINOR_BITS)) { + if (minor >= 256) { write_unlock(&tape_device_lock); return -ENODEV; } diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index da3a4d3ed310..5857f846101f 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -80,7 +80,7 @@ static int tape_proc_show(struct seq_file *m, void *v) static void *tape_proc_start(struct seq_file *m, loff_t *pos) { - if (*pos >= (1 << KDEV_MINOR_BITS) / TAPE_MINORS_PER_DEV) + if (*pos >= 256 / TAPE_MINORS_PER_DEV) return NULL; return (void *)((unsigned long) *pos + 1); } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0a5497ea2389..facb6f9fee35 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -83,7 +83,7 @@ static void sg_proc_cleanup(void); #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ -#define SG_MAX_DEVS_MASK ((1U << KDEV_MINOR_BITS) - 1) +#define SG_MAX_DEVS_MASK (256 - 1) /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 089510b7a819..d3a646260380 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -59,7 +59,7 @@ MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */ -#define SR_DISKS (1 << KDEV_MINOR_BITS) +#define SR_DISKS 256 #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h index 64a88b3b194a..f60508da024d 100644 --- a/include/linux/kdev_t.h +++ b/include/linux/kdev_t.h @@ -1,91 +1,6 @@ #ifndef _LINUX_KDEV_T_H #define _LINUX_KDEV_T_H #ifdef __KERNEL__ -/* -As a preparation for the introduction of larger device numbers, -we introduce a type kdev_t to hold them. No information about -this type is known outside of this include file. - -Objects of type kdev_t designate a device. Outside of the kernel -the corresponding things are objects of type dev_t - usually an -integral type with the device major and minor in the high and low -bits, respectively. Conversion is done by - -extern kdev_t to_kdev_t(int); - -It is up to the various file systems to decide how objects of type -dev_t are stored on disk. -The only other point of contact between kernel and outside world -are the system calls stat and mknod, new versions of which will -eventually have to be used in libc. - -[Unfortunately, the floppy control ioctls fail to hide the internal -kernel structures, and the fd_device field of a struct floppy_drive_struct -is user-visible. So, it remains a dev_t for the moment, with some ugly -conversions in floppy.c.] - -Inside the kernel, we aim for a kdev_t type that is a pointer -to a structure with information about the device (like major, -minor, size, blocksize, sectorsize, name, read-only flag, -struct file_operations etc.). - -However, for the time being we let kdev_t be almost the same as dev_t: - -typedef struct { unsigned short major, minor; } kdev_t; - -Admissible operations on an object of type kdev_t: -- passing it along -- comparing it for equality with another such object -- storing it in inode->i_rdev or tty->device -- using its bit pattern as argument in a hash function -- finding its major and minor -- complaining about it - -An object of type kdev_t is created only by the function MKDEV(), -with the single exception of the constant 0 (no device). - -Right now the other information mentioned above is usually found -in static arrays indexed by major or major,minor. - -An obstacle to immediately using - typedef struct { ... (* lots of information *) } *kdev_t -is the case of mknod used to create a block device that the -kernel doesn't know about at present (but first learns about -when some module is inserted). - -aeb - 950811 -*/ - - -/* - * NOTE NOTE NOTE! - * - * The kernel-internal "kdev_t" will eventually have - * 20 bits for minor numbers, and 12 bits for majors. - * - * HOWEVER, the external representation is still 8+8 - * bits, and there is no way to generate the extended - * "kdev_t" format yet. Which is just as well, since - * we still use "minor" as an index into various - * static arrays, and they are sized for a 8-bit index. - */ -typedef struct { - unsigned short value; -} kdev_t; - -#define KDEV_MINOR_BITS 8 -#define KDEV_MAJOR_BITS 8 - -#define __mkdev(major,minor) (((major) << KDEV_MINOR_BITS) + (minor)) - -#define mk_kdev(major, minor) ((kdev_t) { __mkdev(major,minor) } ) - -#define NODEV (mk_kdev(0,0)) - -/* Mask off the high bits for now.. */ -#define minor(dev) ((dev).value & 0xff) -#define major(dev) (((dev).value >> KDEV_MINOR_BITS) & 0xff) - /* These are for user-level "dev_t" */ #define MINORBITS 8 #define MINORMASK ((1U << MINORBITS) - 1) @@ -94,20 +9,6 @@ typedef struct { #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) -/* - * Conversion functions - */ - -static inline int kdev_t_to_nr(kdev_t dev) -{ - return MKDEV(major(dev), minor(dev)); -} - -static inline kdev_t to_kdev_t(int dev) -{ - return mk_kdev(MAJOR(dev),MINOR(dev)); -} - #define print_dev_t(buffer, dev) \ sprintf((buffer), "%u:%u\n", MAJOR(dev), MINOR(dev)) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 549c7e303144..61ea1a9f2a2b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -57,7 +57,7 @@ * [TO FIX] * ECONNREFUSED is not returned from one end of a connected() socket to the * other the moment one end closes. - * fstat() doesn't return st_dev=NODEV, and give the blksize as high water mark + * fstat() doesn't return st_dev=0, and give the blksize as high water mark * and a fake inode identifier (nor the BSD first socket fstat twice bug). * [NOT TO FIX] * accept() returns a path name even if the connecting socket has closed -- cgit v1.2.3 From b418f8807a80fe7d7cf60067b57ddcd6f2fc42c3 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:27 -0700 Subject: [PATCH] large dev_t - second series (9/15) beginning of fs side work: * new helpers - old_valid_dev(), old_encode_dev() and old_decode_dev() * old_valid_dev() checks if dev_t value is OK for old filesystems (i.e. both major and minor are below 256). * old_valid_dev() calls are added in ->mknod() instances that care about dev_t values (disk-backed and network ones). * old_encode_dev() and old_decode_dev() convert dev_t -> u16 and u16 -> dev_t resp; currently these are no-ops, places that use current formar (minor in bits 0--7, major in bits 8--15) will switch to these before we widen dev_t. --- fs/cifs/dir.c | 3 +++ fs/coda/dir.c | 3 +++ fs/ext2/namei.c | 10 ++++++++-- fs/ext3/namei.c | 3 +++ fs/hpfs/namei.c | 2 ++ fs/intermezzo/dir.c | 3 +++ fs/jffs/inode-v23.c | 2 ++ fs/jffs2/dir.c | 3 +++ fs/jfs/namei.c | 3 +++ fs/libfs.c | 20 ++++++++++++++++++++ fs/minix/namei.c | 7 ++++++- fs/ncpfs/dir.c | 2 ++ fs/nfs/dir.c | 3 +++ fs/reiserfs/namei.c | 3 +++ fs/smbfs/dir.c | 3 +++ fs/sysv/namei.c | 10 ++++++++-- fs/udf/namei.c | 3 +++ fs/ufs/namei.c | 5 ++++- fs/xfs/linux/xfs_iops.c | 3 +++ include/linux/fs.h | 3 +++ 20 files changed, 88 insertions(+), 6 deletions(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 8873ca0447c9..b1245a53db80 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -265,6 +265,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev char *full_path = NULL; struct inode * newinode = NULL; + if (!old_valid_dev(device_number)) + return -EINVAL; + xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 2917ab9f4976..4c75d774e0dd 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -242,6 +242,9 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev if ( coda_hasmknod == 0 ) return -EIO; + if (!old_valid_dev(rdev)) + return -EINVAL; + lock_kernel(); coda_vfs_stat.create++; diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 72d5690b2450..8079e2ee4684 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -139,8 +139,14 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { - struct inode * inode = ext2_new_inode (dir, mode); - int err = PTR_ERR(inode); + struct inode * inode; + int err; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = ext2_new_inode (dir, mode); + err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); #ifdef CONFIG_EXT2_FS_XATTR diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 78daed5cee0f..769392cf8ea9 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1659,6 +1659,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, struct inode *inode; int err; + if (!old_valid_dev(rdev)) + return -EINVAL; + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); if (IS_ERR(handle)) diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 18f8b1c00e93..030d3de7d01f 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -194,6 +194,8 @@ int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) int err; if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err; if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM; + if (!old_valid_dev(rdev)) + return -EINVAL; lock_kernel(); if (!(fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh))) goto bail; memset(&dee, 0, sizeof dee); diff --git a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c index 4794ee0a3822..b07d6ae8bb74 100644 --- a/fs/intermezzo/dir.c +++ b/fs/intermezzo/dir.c @@ -726,6 +726,9 @@ static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, de struct dentry *parent = dentry->d_parent; struct lento_vfs_context info; + if (!old_valid_dev(rdev)) + return -EINVAL; + ENTRY; error = presto_check_set_fsdata(dentry); if ( error ) { diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 480a5ba41972..cad1a1f36e15 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1086,6 +1086,8 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) D1(printk("***jffs_mknod()\n")); + if (!old_valid_dev(rdev)) + return -EINVAL; lock_kernel(); dir_f = (struct jffs_file *)dir->u.generic_ip; c = dir_f->c; diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 9a2df58cb486..068084e7893e 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -594,6 +594,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mk uint32_t writtenlen; int ret; + if (!old_valid_dev(rdev)) + return -EINVAL; + ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 5062dc50b02d..ee62b39ee46c 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1311,6 +1311,9 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) tid_t tid; struct tblock *tblk; + if (!old_valid_dev(rdev)) + return -EINVAL; + jfs_info("jfs_mknod: %s", dentry->d_name.name); if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dir->i_sb)->nls_tab))) diff --git a/fs/libfs.c b/fs/libfs.c index befcf41b0e30..fbf1d0e6e3e4 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -3,6 +3,7 @@ * Library for filesystems writers. */ +#include #include #include #include @@ -428,3 +429,22 @@ void simple_release_fs(struct vfsmount **mount, int *count) spin_unlock(&pin_fs_lock); mntput(mnt); } + +/* acceptable for old filesystems */ +int old_valid_dev(dev_t dev) +{ + return MAJOR(dev) < 256 && MINOR(dev) < 256; +} +EXPORT_SYMBOL(old_valid_dev); + +u16 old_encode_dev(dev_t dev) +{ + return (MAJOR(dev) << 8) | MINOR(dev); +} +EXPORT_SYMBOL(old_encode_dev); + +dev_t old_decode_dev(u16 val) +{ + return MKDEV((val >> 8) & 255, val & 255); +} +EXPORT_SYMBOL(old_decode_dev); diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 2b9e6c64d25a..9f2682641f7f 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -78,7 +78,12 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, st static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { int error; - struct inode * inode = minix_new_inode(dir, &error); + struct inode *inode; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = minix_new_inode(dir, &error); if (inode) { inode->i_mode = mode; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index f10460e559a5..ce75e852e757 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -1170,6 +1170,8 @@ out: static int ncp_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { + if (!old_valid_dev(rdev)) + return -EINVAL; if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode); return ncp_create_new(dir, dentry, mode, rdev, 0); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e7ba8d084182..f9f494a60e4b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -859,6 +859,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); + if (!old_valid_dev(rdev)) + return -EINVAL; + attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 85dddb7a83b3..8c1485504ffe 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -613,6 +613,9 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; + if (!old_valid_dev(rdev)) + return -EINVAL; + if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index f0b62740ae89..aa5974edc203 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -661,6 +661,9 @@ smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) attr.ia_uid = current->euid; attr.ia_gid = current->egid; + if (!old_valid_dev(dev)) + return -EINVAL; + smb_invalid_dir_cache(dir); error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev)); if (!error) { diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index cbf08f04d07c..c24d0be87e74 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -85,8 +85,14 @@ static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, st static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) { - struct inode * inode = sysv_new_inode(dir, mode); - int err = PTR_ERR(inode); + struct inode * inode; + int err; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = sysv_new_inode(dir, mode); + err = PTR_ERR(inode); if (!IS_ERR(inode)) { sysv_set_inode(inode, rdev); diff --git a/fs/udf/namei.c b/fs/udf/namei.c index d2ac88dae447..a7350413f9b8 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -677,6 +677,9 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t int err; struct fileIdentDesc cfi, *fi; + if (!old_valid_dev(rdev)) + return -EINVAL; + lock_kernel(); err = -EIO; inode = udf_new_inode(dir, mode, &err); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 82f391298c48..e59b6a81e558 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -111,7 +111,10 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode, static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { - struct inode * inode = ufs_new_inode(dir, mode); + struct inode * inode; + if (!old_valid_dev(rdev)) + return -EINVAL; + inode = ufs_new_inode(dir, mode); int err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); diff --git a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c index 5f316085b1b9..cb9bcdda6d01 100644 --- a/fs/xfs/linux/xfs_iops.c +++ b/fs/xfs/linux/xfs_iops.c @@ -113,6 +113,9 @@ linvfs_mknod( xattr_exists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; + if (!old_valid_dev(rdev)) + return -EINVAL; + if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; diff --git a/include/linux/fs.h b/include/linux/fs.h index fe2bfd295802..d10db09f6164 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1389,6 +1389,9 @@ struct tree_descr { char *name; struct file_operations *ops; int mode; }; extern int simple_fill_super(struct super_block *, int, struct tree_descr *); extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); extern void simple_release_fs(struct vfsmount **mount, int *count); +extern int old_valid_dev(dev_t); +extern u16 old_encode_dev(dev_t); +extern dev_t old_decode_dev(u16); extern int inode_change_ok(struct inode *, struct iattr *); extern int inode_setattr(struct inode *, struct iattr *); -- cgit v1.2.3 From d84b5b0b136c253e8d29e41be6ce363384f82927 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:36 -0700 Subject: [PATCH] large dev_t - second series (10/15) Fix for endianness bug in UDF: it writes major and minor as 32bit host-endian and reads them as 32bit little-endian; obviously a bad idea on big-endian boxen ;-) Needed both for 2.4 and 2.6. --- fs/udf/inode.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 1c2fba3d5655..d892081d73ab 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1234,9 +1234,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) if (dsea) { - init_special_inode(inode, inode->i_mode, - ((le32_to_cpu(dsea->majorDeviceIdent)) << 8) | - (le32_to_cpu(dsea->minorDeviceIdent) & 0xFF)); + init_special_inode(inode, inode->i_mode, MKDEV( + le32_to_cpu(dsea->majorDeviceIdent), + le32_to_cpu(dsea->minorDeviceIdent) + )); /* Developer ID ??? */ udf_release_data(tbh); } @@ -1392,8 +1393,8 @@ udf_update_inode(struct inode *inode, int do_sync) strcpy(eid->ident, UDF_ID_DEVELOPER); eid->identSuffix[0] = UDF_OS_CLASS_UNIX; eid->identSuffix[1] = UDF_OS_ID_LINUX; - dsea->majorDeviceIdent = inode->i_rdev >> 8; - dsea->minorDeviceIdent = inode->i_rdev & 0xFF; + dsea->majorDeviceIdent = cpu_to_le32(imajor(inode)); + dsea->minorDeviceIdent = cpu_to_le32(iminor(inode)); mark_buffer_dirty_inode(tbh, inode); udf_release_data(tbh); } -- cgit v1.2.3 From ec55b83db70e2dd10feae0b0cff2fc29dfdbdeb7 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:44 -0700 Subject: [PATCH] large dev_t - second series (11/15) Fix for JFS handling of device nodes; it has 32bit on-disk device numbers, shoves them into 16bit (->i_rdev) when inode is read and writes them back truncated when inode is written to disk. For now (and 2.4 will have to do the same permanently) we store the original value in private part of inode and use it instead of ->i_rdev in ->write_inode(); mknod() sets it at the same time as ->i_rdev. It will become unnecessary when dev_t becomes wider than 16 bits, but for now we need it. --- fs/jfs/jfs_imap.c | 7 +++---- fs/jfs/jfs_incore.h | 3 ++- fs/jfs/jfs_mount.c | 2 +- fs/jfs/namei.c | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 7ee8f04862cc..cb40b149bd12 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -3041,9 +3041,10 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) jfs_ip->next_index = le32_to_cpu(dip->di_next_index); jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec); jfs_ip->acltype = le32_to_cpu(dip->di_acltype); + jfs_ip->dev = le32_to_cpu(dip->di_rdev); if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - ip->i_rdev = le32_to_cpu(dip->di_rdev); + ip->i_rdev = old_decode_dev(jfs_ip->dev); if (S_ISDIR(ip->i_mode)) { memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384); @@ -3100,9 +3101,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip) dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime); dip->di_otime.tv_nsec = 0; dip->di_acltype = cpu_to_le32(jfs_ip->acltype); - - if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - dip->di_rdev = cpu_to_le32(ip->i_rdev); + dip->di_rdev = cpu_to_le32(jfs_ip->dev); } #ifdef _JFS_DEBUG_IMAP diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 2164d5cdfc10..15a99b075387 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -93,6 +93,7 @@ struct jfs_inode_info { unchar _inline_ea[128]; /* 128: inline extended attr */ } link; } u; + u32 dev; /* will die when we get wide dev_t */ struct inode vfs_inode; }; #define i_xtroot u.file._xtroot @@ -143,7 +144,7 @@ struct jfs_sb_info { short nbperpage; /* blocks per page */ short l2nbperpage; /* log2 blocks per page */ short l2niperblk; /* log2 inodes per page */ - u32 logdev; /* external log device */ + dev_t logdev; /* external log device */ uint aggregate; /* volume identifier in log record */ pxd_t logpxd; /* pxd describing log */ pxd_t fsckpxd; /* pxd describing fsck wkspc */ diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index b97311299412..4180b7c87d8d 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -395,7 +395,7 @@ static int chkSuper(struct super_block *sb) if (sbi->mntflag & JFS_INLINELOG) sbi->logpxd = j_sb->s_logpxd; else { - sbi->logdev = le32_to_cpu(j_sb->s_logdev); + sbi->logdev = old_decode_dev(le32_to_cpu(j_sb->s_logdev)); memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); } diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index ee62b39ee46c..71f3ccf53b77 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1302,6 +1302,7 @@ int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { + struct jfs_inode_info *jfs_ip; struct btstack btstack; struct component_name dname; ino_t ino; @@ -1324,6 +1325,7 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) rc = -ENOSPC; goto out1; } + jfs_ip = JFS_IP(ip); tid = txBegin(dir->i_sb, 0); @@ -1342,6 +1344,7 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) goto out3; ip->i_op = &jfs_file_inode_operations; + jfs_ip->dev = old_encode_dev(rdev); init_special_inode(ip, ip->i_mode, rdev); insert_inode_hash(ip); -- cgit v1.2.3 From e89e1d3be6007d317f78fc28d00a92059eeedbdd Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:54:53 -0700 Subject: [PATCH] large dev_t - second series (12/15) Similar fix for UFS; touching device node (and they have 32bit dev_t) ends up killing upper 16 bits, which makes for very unhappy *BSD, since that turns /dev/ad0s1 into alias of /dev/ad0. Again, for now we store on-disk value in private part of inode and use it instead of ->i_rdev in ->write_inode(). --- fs/ufs/inode.c | 16 ++++++++-------- fs/ufs/namei.c | 4 ++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index f8c113bd3677..647c7bef9680 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -475,6 +475,7 @@ void ufs_read_inode (struct inode * inode) struct ufs_sb_private_info * uspi; struct ufs_inode * ufs_inode; struct buffer_head * bh; + mode_t mode; unsigned i; unsigned flags; @@ -500,7 +501,7 @@ void ufs_read_inode (struct inode * inode) /* * Copy data to the in-core inode. */ - inode->i_mode = fs16_to_cpu(sb, ufs_inode->ui_mode); + inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); if (inode->i_nlink == 0) ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); @@ -527,9 +528,7 @@ void ufs_read_inode (struct inode * inode) ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ; - else if (inode->i_blocks) { + if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; } @@ -555,7 +554,7 @@ void ufs_read_inode (struct inode * inode) } } else init_special_inode(inode, inode->i_mode, - fs32_to_cpu(sb, ufs_inode->ui_u2.ui_addr.ui_db[0])); + old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0]))); brelse (bh); @@ -618,9 +617,10 @@ static int ufs_update_inode(struct inode * inode, int do_sync) ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); } - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); - else if (inode->i_blocks) { + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ + ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; + } else if (inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; } diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index e59b6a81e558..224d2c08d771 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -29,6 +29,7 @@ #include #include #include +#include "swab.h" /* will go away - see comment in mknod() */ #undef UFS_NAMEI_DEBUG @@ -118,6 +119,9 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t int err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); + /* NOTE: that'll go when we get wide dev_t */ + UFS_I(inode)->i_u1.i_data[0] = cpu_to_fs32(inode->i_sb, + old_encode_dev(rdev)); mark_inode_dirty(inode); lock_kernel(); err = ufs_add_nondir(dentry, inode); -- cgit v1.2.3 From 81eec8eb4f3e62dd506f032a7520f6b79f626a9c Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:55:01 -0700 Subject: [PATCH] large dev_t - second series (13/15) HPFS code that uses EAs for storing i_rdev/i_mode/i_uid/i_gid sanitized. --- fs/hpfs/inode.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 94293028a9ec..7b0a4f1c7fbc 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -114,14 +114,14 @@ void hpfs_read_inode(struct inode *i) if (hpfs_sb(i->i_sb)->sb_eas) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) { if (ea_size == 2) { - i->i_uid = ea[0] + (ea[1] << 8); + i->i_uid = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_uid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) { if (ea_size == 2) { - i->i_gid = ea[0] + (ea[1] << 8); + i->i_gid = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_gid = 1; } kfree(ea); @@ -141,7 +141,7 @@ void hpfs_read_inode(struct inode *i) int rdev = 0; umode_t mode = hpfs_sb(sb)->sb_mode; if (ea_size == 2) { - mode = ea[0] + (ea[1] << 8); + mode = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_mode = 1; } kfree(ea); @@ -149,7 +149,7 @@ void hpfs_read_inode(struct inode *i) if (S_ISBLK(mode) || S_ISCHR(mode)) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) { if (ea_size == 4) - rdev = ea[0] + (ea[1] << 8) + (ea[2] << 16) + (ea[3] << 24); + rdev = le32_to_cpu(*(u32*)ea); kfree(ea); } } @@ -158,7 +158,8 @@ void hpfs_read_inode(struct inode *i) i->i_nlink = 1; i->i_size = 0; i->i_blocks = 1; - init_special_inode(i, mode, rdev); + init_special_inode(i, mode, + old_decode_dev(rdev)); return; } } @@ -201,17 +202,15 @@ void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) we'd better not overwrite them */ hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); } else if (hpfs_sb(i->i_sb)->sb_eas >= 2) { - unsigned char ea[4]; + u32 ea; if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) { - ea[0] = i->i_uid & 0xff; - ea[1] = i->i_uid >> 8; - hpfs_set_ea(i, fnode, "UID", ea, 2); + ea = cpu_to_le32(i->i_uid); + hpfs_set_ea(i, fnode, "UID", (char*)&ea, 2); hpfs_inode->i_ea_uid = 1; } if ((i->i_gid != hpfs_sb(i->i_sb)->sb_gid) || hpfs_inode->i_ea_gid) { - ea[0] = i->i_gid & 0xff; - ea[1] = i->i_gid >> 8; - hpfs_set_ea(i, fnode, "GID", ea, 2); + ea = cpu_to_le32(i->i_gid); + hpfs_set_ea(i, fnode, "GID", (char *)&ea, 2); hpfs_inode->i_ea_gid = 1; } if (!S_ISLNK(i->i_mode)) @@ -219,18 +218,13 @@ void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) | (S_ISDIR(i->i_mode) ? S_IFDIR : S_IFREG)) && i->i_mode != ((hpfs_sb(i->i_sb)->sb_mode & ~(S_ISDIR(i->i_mode) ? 0222 : 0333)) | (S_ISDIR(i->i_mode) ? S_IFDIR : S_IFREG))) || hpfs_inode->i_ea_mode) { - ea[0] = i->i_mode & 0xff; - ea[1] = i->i_mode >> 8; - hpfs_set_ea(i, fnode, "MODE", ea, 2); + ea = cpu_to_le32(i->i_mode); + hpfs_set_ea(i, fnode, "MODE", (char *)&ea, 2); hpfs_inode->i_ea_mode = 1; } if (S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode)) { - dev_t d = i->i_rdev; - ea[0] = d & 0xff; - ea[1] = (d >> 8) & 0xff; - ea[2] = (d >> 16) & 0xff; - ea[3] = d >> 24; - hpfs_set_ea(i, fnode, "DEV", ea, 4); + ea = cpu_to_le32(old_encode_dev(i->i_rdev)); + hpfs_set_ea(i, fnode, "DEV", (char *)&ea, 4); } } } -- cgit v1.2.3 From 0dbd0f6805c0febd2f080e6aa82e24d864be5c27 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:55:10 -0700 Subject: [PATCH] large dev_t - second series (14/15) nfs_fattr->rdev switched to dev_t; code that unpacks on-the-wire attributes does explicit conversion now. --- fs/nfs/nfs2xdr.c | 6 ++++-- include/linux/nfs_xdr.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 1461252f66fe..d5f552dd7f4e 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -106,6 +106,7 @@ xdr_decode_time(u32 *p, struct timespec *timep) static u32 * xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) { + u32 rdev; fattr->type = (enum nfs_ftype) ntohl(*p++); fattr->mode = ntohl(*p++); fattr->nlink = ntohl(*p++); @@ -113,7 +114,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) fattr->gid = ntohl(*p++); fattr->size = ntohl(*p++); fattr->du.nfs2.blocksize = ntohl(*p++); - fattr->rdev = ntohl(*p++); + rdev = ntohl(*p++); fattr->du.nfs2.blocks = ntohl(*p++); fattr->fsid_u.nfs3 = ntohl(*p++); fattr->fileid = ntohl(*p++); @@ -121,7 +122,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) p = xdr_decode_time(p, &fattr->mtime); p = xdr_decode_time(p, &fattr->ctime); fattr->valid |= NFS_ATTR_FATTR; - if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) { + fattr->rdev = old_decode_dev(rdev); + if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) { fattr->type = NFFIFO; fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; fattr->rdev = 0; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 3d46a2caaade..88b705d8cefe 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -23,7 +23,7 @@ struct nfs_fattr { __u64 used; } nfs3; } du; - __u32 rdev; + dev_t rdev; union { __u64 nfs3; /* also nfs2 */ struct { -- cgit v1.2.3 From a1f6ff2111185f13b8611e3744b8ad272e53e10a Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Thu, 4 Sep 2003 20:55:21 -0700 Subject: [PATCH] large dev_t - second series (15/15) old_decode_dev()/old_encode_dev() added where needed in other filesystems. Parts in different filesystems are independent, but IMO it's not worse splitting into a dozen of half-kilobyte patches. --- fs/cramfs/inode.c | 3 ++- fs/efs/inode.c | 2 +- fs/ext2/inode.c | 4 ++-- fs/ext3/inode.c | 4 ++-- fs/ext3/super.c | 2 +- fs/freevxfs/vxfs_inode.c | 2 +- fs/intermezzo/journal.c | 10 ++++------ fs/intermezzo/kml_reint.c | 5 +++-- fs/intermezzo/vfs.c | 2 +- fs/jffs/inode-v23.c | 6 ++---- fs/jffs2/dir.c | 2 +- fs/jffs2/fs.c | 3 ++- fs/minix/inode.c | 8 ++++---- fs/ncpfs/dir.c | 4 ++-- fs/ncpfs/inode.c | 3 ++- fs/nfsd/nfsproc.c | 3 ++- fs/reiserfs/inode.c | 6 +++--- fs/reiserfs/journal.c | 3 +-- fs/sysv/inode.c | 14 +++++++------- 19 files changed, 43 insertions(+), 43 deletions(-) diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 1789afd1298d..8fcd03bec9f7 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -71,7 +71,8 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; - init_special_inode(inode, inode->i_mode, cramfs_inode->size); + init_special_inode(inode, inode->i_mode, + old_decode_dev(cramfs_inode->size)); } } return inode; diff --git a/fs/efs/inode.c b/fs/efs/inode.c index e0a73e28e004..5901ab61e0b1 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -117,7 +117,7 @@ void efs_read_inode(struct inode *inode) { * to see whether odev contains 65535. if this is the case then we * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev). */ - device = be16_to_cpu(efs_inode->di_u.di_dev.odev); + device = old_decode_dev(be16_to_cpu(efs_inode->di_u.di_dev.odev)); /* get the number of extents for this object */ in->numextents = be16_to_cpu(efs_inode->di_numextents); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c9d6cf4a3869..9247dc703f31 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1127,7 +1127,7 @@ void ext2_read_inode (struct inode * inode) } else { inode->i_op = &ext2_special_inode_operations; init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); + old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); } brelse (bh); ext2_set_inode_flags(inode); @@ -1216,7 +1216,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_block[0] = cpu_to_le32(inode->i_rdev); + raw_inode->i_block[0] = cpu_to_le32(old_encode_dev(inode->i_rdev)); else for (n = 0; n < EXT2_N_BLOCKS; n++) raw_inode->i_block[n] = ei->i_data[n]; mark_buffer_dirty(bh); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 24bd9d1fc7de..c4fc83552763 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2566,7 +2566,7 @@ void ext3_read_inode(struct inode * inode) } else { inode->i_op = &ext3_special_inode_operations; init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); + old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); } brelse (iloc.bh); ext3_set_inode_flags(inode); @@ -2668,7 +2668,7 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = - cpu_to_le32(inode->i_rdev); + cpu_to_le32(old_encode_dev(inode->i_rdev)); else for (block = 0; block < EXT3_N_BLOCKS; block++) raw_inode->i_block[block] = ei->i_data[block]; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 4ac414b82e68..e5148cb001d8 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1603,7 +1603,7 @@ static int ext3_load_journal(struct super_block * sb, { journal_t *journal; int journal_inum = le32_to_cpu(es->s_journal_inum); - dev_t journal_dev = le32_to_cpu(es->s_journal_dev); + dev_t journal_dev = old_decode_dev(le32_to_cpu(es->s_journal_dev)); int err = 0; int really_read_only; diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 06d7fe84a421..bbaeef8b63d2 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -333,7 +333,7 @@ vxfs_read_inode(struct inode *ip) } else ip->i_op = &vxfs_immed_symlink_iops; } else - init_special_inode(ip, ip->i_mode, vip->vii_rdev); + init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); return; } diff --git a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c index 0b62b1364855..74396076f10d 100644 --- a/fs/intermezzo/journal.c +++ b/fs/intermezzo/journal.c @@ -391,13 +391,11 @@ static inline char *log_version(char *buf, struct presto_version *pv) static inline char *log_rollback(char *buf, struct izo_rollback_data *rb) { struct izo_rollback_data rollback; - - memcpy(&rollback, rb, sizeof(rollback)); - rollback.rb_mode = HTON__u32(rollback.rb_mode); - rollback.rb_rdev = HTON__u32(rollback.rb_rdev); - rollback.rb_uid = HTON__u64(rollback.rb_uid); - rollback.rb_gid = HTON__u64(rollback.rb_gid); + rollback.rb_mode = HTON__u32(rb->rb_mode); + rollback.rb_rdev = HTON__u32(rb->rb_rdev); + rollback.rb_uid = HTON__u64(rb->rb_uid); + rollback.rb_gid = HTON__u64(rb->rb_gid); return logit(buf, &rollback, sizeof(rollback)); } diff --git a/fs/intermezzo/kml_reint.c b/fs/intermezzo/kml_reint.c index f05915ee0dc0..f244abb962f9 100644 --- a/fs/intermezzo/kml_reint.c +++ b/fs/intermezzo/kml_reint.c @@ -236,7 +236,8 @@ static int reint_mknod(struct kml_rec *rec, struct file *dir, struct lento_vfs_context *info) { struct run_ctxt saved_ctxt; - int error, dev; + int error; + dev_t dev; ENTRY; @@ -245,7 +246,7 @@ static int reint_mknod(struct kml_rec *rec, struct file *dir, info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec; kmlreint_pre_secure(rec, dir, &saved_ctxt); - dev = rec->rdev ?: MKDEV(rec->major, rec->minor); + dev = rec->rdev ? old_decode_dev(rec->rdev) : MKDEV(rec->major, rec->minor); error = lento_mknod(rec->path, rec->mode, dev, info); pop_ctxt(&saved_ctxt); diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c index 469a463c8752..40b08d332d25 100644 --- a/fs/intermezzo/vfs.c +++ b/fs/intermezzo/vfs.c @@ -290,7 +290,7 @@ int presto_settime(struct presto_file_set *fset, void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb) { rb->rb_mode = (__u32)inode->i_mode; - rb->rb_rdev = (__u32)inode->i_rdev; + rb->rb_rdev = (__u32)old_encode_dev(inode->i_rdev); rb->rb_uid = (__u64)inode->i_uid; rb->rb_gid = (__u64)inode->i_gid; } diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index cad1a1f36e15..915f3a57af46 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1079,11 +1079,9 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) struct jffs_control *c; struct inode *inode; int result = 0; - u16 data; + u16 data = old_encode_dev(rdev); int err; - data = (MAJOR(rdev) << 8) | MINOR(rdev); - D1(printk("***jffs_mknod()\n")); if (!old_valid_dev(rdev)) @@ -1738,7 +1736,7 @@ jffs_read_inode(struct inode *inode) u16 val; jffs_read_data(f, (char *)val, 0, 2); init_special_inode(inode, inode->i_mode, - MKDEV((val >> 8) & 255, val & 255)); + old_decode_dev(val)); } D3(printk (KERN_NOTICE "read_inode(): up biglock\n")); diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 068084e7893e..93742552a9e9 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -604,7 +604,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mk c = JFFS2_SB_INFO(dir_i->i_sb); if (S_ISBLK(mode) || S_ISCHR(mode)) { - dev = cpu_to_je16((MAJOR(rdev) << 8) | MINOR(rdev)); + dev = cpu_to_je16(old_encode_dev(rdev)); devlen = sizeof(dev); } diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 88464374eaf1..531d79dea640 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -147,7 +147,8 @@ void jffs2_read_inode (struct inode *inode) case S_IFSOCK: case S_IFIFO: inode->i_op = &jffs2_file_inode_operations; - init_special_inode(inode, inode->i_mode, MKDEV(je16_to_cpu(rdev)>>8, je16_to_cpu(rdev)&0xff)); + init_special_inode(inode, inode->i_mode, + old_decode_dev(je16_to_cpu(rdev))); break; default: diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 1c98d1103729..946f5812efc1 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -392,7 +392,7 @@ static void V1_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (i = 0; i < 9; i++) minix_inode->u.i1_data[i] = raw_inode->i_zone[i]; - minix_set_inode(inode, raw_inode->i_zone[0]); + minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); } @@ -425,7 +425,7 @@ static void V2_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (i = 0; i < 10; i++) minix_inode->u.i2_data[i] = raw_inode->i_zone[i]; - minix_set_inode(inode, raw_inode->i_zone[0]); + minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); } @@ -460,7 +460,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode) raw_inode->i_size = inode->i_size; raw_inode->i_time = inode->i_mtime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = inode->i_rdev; + raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); else for (i = 0; i < 9; i++) raw_inode->i_zone[i] = minix_inode->u.i1_data[i]; mark_buffer_dirty(bh); @@ -489,7 +489,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode) raw_inode->i_atime = inode->i_atime.tv_sec; raw_inode->i_ctime = inode->i_ctime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = inode->i_rdev; + raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); else for (i = 0; i < 10; i++) raw_inode->i_zone[i] = minix_inode->u.i2_data[i]; mark_buffer_dirty(bh); diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index ce75e852e757..0e84d722cf0b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -929,10 +929,10 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, finfo.access = opmode; if (ncp_is_nfs_extras(server, finfo.volume)) { finfo.i.nfs.mode = mode; - finfo.i.nfs.rdev = rdev; + finfo.i.nfs.rdev = old_encode_dev(rdev); if (ncp_modify_nfs_info(server, finfo.volume, finfo.i.dirEntNum, - mode, rdev) != 0) + mode, old_encode_dev(rdev)) != 0) goto out; } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index d0bd5276de56..f3fe78dbfb66 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -261,7 +261,8 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) inode->i_fop = &ncp_dir_operations; #ifdef CONFIG_NCPFS_NFS_NS } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - init_special_inode(inode, inode->i_mode, info->i.nfs.rdev); + init_special_inode(inode, inode->i_mode, + old_decode_dev(info->i.nfs.rdev)); #endif #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) } else if (S_ISLNK(inode->i_mode)) { diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index d0dda80f9c47..c64ebaf8818e 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -279,7 +279,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, int is_borc = 0; u32 size = attr->ia_size; - rdev = (dev_t) size; + /* may need to change when we widen dev_t */ + rdev = old_decode_dev(size); if (type != S_IFBLK && type != S_IFCHR) { rdev = 0; } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index d18538e49f21..e33ddbab7552 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1003,7 +1003,7 @@ static void init_inode (struct inode * inode, struct path * path) inode->i_mapping->a_ops = &reiserfs_address_space_operations; } else { inode->i_blocks = 0; - init_special_inode(inode, inode->i_mode, rdev) ; + init_special_inode(inode, inode->i_mode, old_decode_dev(rdev)); } } @@ -1024,7 +1024,7 @@ static void inode2sd (void * sd, struct inode * inode) set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec ); set_sd_v2_blocks(sd_v2, inode->i_blocks ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v2_rdev(sd_v2, inode->i_rdev); + set_sd_v2_rdev(sd_v2, old_encode_dev(inode->i_rdev)); else set_sd_v2_generation(sd_v2, inode->i_generation); flags = REISERFS_I(inode)->i_attrs; @@ -1048,7 +1048,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode) set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v1_rdev(sd_v1, inode->i_rdev); + set_sd_v1_rdev(sd_v1, old_encode_dev(inode->i_rdev)); else set_sd_v1_blocks(sd_v1, inode->i_blocks ); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 55f12082022b..803d414747e3 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1906,7 +1906,7 @@ static int journal_init_dev( struct super_block *super, journal -> j_dev_bd = NULL; journal -> j_dev_file = NULL; jdev = SB_ONDISK_JOURNAL_DEVICE( super ) ? - SB_ONDISK_JOURNAL_DEVICE( super ) : super->s_dev; + old_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev; if (bdev_read_only(super->s_bdev)) blkdev_mode = FMODE_READ; @@ -1939,7 +1939,6 @@ static int journal_init_dev( struct super_block *super, result = -ENOMEM; } else { /* ok */ - jdev = jdev_inode -> i_bdev -> bd_dev; set_blocksize(journal->j_dev_bd, super->s_blocksize); } } else { diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 60fca2128567..09c131fbb36f 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -164,10 +164,8 @@ static void sysv_read_inode(struct inode *inode) struct buffer_head * bh; struct sysv_inode * raw_inode; struct sysv_inode_info * si; - unsigned int block, ino; - dev_t rdev = 0; + unsigned int block, ino = inode->i_ino; - ino = inode->i_ino; if (!ino || ino > sbi->s_ninodes) { printk("Bad inode number on dev %s: %d is out of range\n", inode->i_sb->s_id, ino); @@ -198,10 +196,12 @@ static void sysv_read_inode(struct inode *inode) read3byte(sbi, &raw_inode->i_data[3*block], (u8 *)&si->i_data[block]); brelse(bh); - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - rdev = (u16)fs32_to_cpu(sbi, si->i_data[0]); si->i_dir_start_lookup = 0; - sysv_set_inode(inode, rdev); + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + sysv_set_inode(inode, + old_decode_dev(fs32_to_cpu(sbi, si->i_data[0]))); + else + sysv_set_inode(inode, 0); return; bad_inode: @@ -241,7 +241,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) si = SYSV_I(inode); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - si->i_data[0] = cpu_to_fs32(sbi, inode->i_rdev); + si->i_data[0] = cpu_to_fs32(sbi, old_encode_dev(inode->i_rdev)); for (block = 0; block < 10+1+1+1; block++) write3byte(sbi, (u8 *)&si->i_data[block], &raw_inode->i_data[3*block]); -- cgit v1.2.3 From d04668a76d3780540b30bcbc2bc638f3f31d577d Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Thu, 4 Sep 2003 21:42:15 -0700 Subject: [PATCH] Common PROT_xxx -> VM_xxx mapping This moves the mapping of PROT_* bits to VM_* bits from mmap.c to the common header file . The mapping is needed for mprotect too. --- include/linux/mman.h | 29 +++++++++++++++++++++++++++++ mm/mmap.c | 27 ++------------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/include/linux/mman.h b/include/linux/mman.h index a8956f6588ad..cfb6ac61bbde 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -2,6 +2,7 @@ #define _LINUX_MMAN_H #include +#include #include #include @@ -27,4 +28,32 @@ static inline void vm_unacct_memory(long pages) vm_acct_memory(-pages); } +/* Optimisation macro. */ +#define _calc_vm_trans(x,bit1,bit2) \ + ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \ + : ((x) & (bit1)) / ((bit1) / (bit2))) + +/* + * Combine the mmap "prot" argument into "vm_flags" used internally. + */ +static inline unsigned long +calc_vm_prot_bits(unsigned long prot) +{ + return _calc_vm_trans(prot, PROT_READ, VM_READ ) | + _calc_vm_trans(prot, PROT_WRITE, VM_WRITE) | + _calc_vm_trans(prot, PROT_EXEC, VM_EXEC ); +} + +/* + * Combine the mmap "flags" argument into "vm_flags" used internally. + */ +static inline unsigned long +calc_vm_flag_bits(unsigned long flags) +{ + return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | + _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | + _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) | + _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); +} + #endif /* _LINUX_MMAN_H */ diff --git a/mm/mmap.c b/mm/mmap.c index bcc28864eab6..61c9f5ca5f82 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -136,29 +136,6 @@ out: return retval; } -/* Combine the mmap "prot" and "flags" argument into one "vm_flags" used - * internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits - * into "VM_xxx". - */ -static inline unsigned long -calc_vm_flags(unsigned long prot, unsigned long flags) -{ -#define _trans(x,bit1,bit2) \ -((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) - - unsigned long prot_bits, flag_bits; - prot_bits = - _trans(prot, PROT_READ, VM_READ) | - _trans(prot, PROT_WRITE, VM_WRITE) | - _trans(prot, PROT_EXEC, VM_EXEC); - flag_bits = - _trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) | - _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) | - _trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE); - return prot_bits | flag_bits; -#undef _trans -} - #ifdef DEBUG_MM_RB static int browse_rb(struct rb_node * rb_node) { int i = 0; @@ -500,8 +477,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, * to. we assume access permissions have been handled by the open * of the memory object, so we don't do any here. */ - vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | + mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; if (flags & MAP_LOCKED) { if (!capable(CAP_IPC_LOCK)) -- cgit v1.2.3 From 3377ea439d36704aeb80da6907a62047ba6ade09 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 4 Sep 2003 22:05:07 -0700 Subject: Fix mprotect() to do proper PROT_xxx -> VM_xxx translation. This also fixes the bug with MAP_SEM being potentially interpreted as VM_SHARED. --- mm/mprotect.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mm/mprotect.c b/mm/mprotect.c index 2c015794e3c1..699962ebd1e4 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -224,7 +224,7 @@ fail: asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) { - unsigned long nstart, end, tmp; + unsigned long vm_flags, nstart, end, tmp; struct vm_area_struct * vma, * next, * prev; int error = -EINVAL; @@ -239,6 +239,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) if (end == start) return 0; + vm_flags = calc_vm_prot_bits(prot); + down_write(¤t->mm->mmap_sem); vma = find_vma_prev(current->mm, start, &prev); @@ -257,7 +259,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) goto out; } - newflags = prot | (vma->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC)); + newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); + if ((newflags & ~(newflags >> 4)) & 0xf) { error = -EACCES; goto out; -- cgit v1.2.3 From 47226136c0eddf60e677297326f2aee3d678e826 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Sep 2003 17:19:00 +0100 Subject: [CPUFREQ] Print out FSB in longhaul debug info --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 7bc5d8309bc9..a271dd57c1d5 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -236,8 +236,8 @@ static int __init longhaul_get_ranges (void) minmult/10, minmult%10, maxmult/10, maxmult%10); highest_speed = calc_speed (maxmult, fsb); lowest_speed = calc_speed (minmult,fsb); - dprintk (KERN_INFO PFX "Lowestspeed=%dMHz Highestspeed=%dMHz\n", - lowest_speed, highest_speed); + dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", + fsb, lowest_speed, highest_speed); longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) -- cgit v1.2.3 From fa1d243483f93f00710fe61b75fc0b22773bd9a1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Sep 2003 17:38:20 +0100 Subject: [CPUFREQ] Print out CPU name in debug info. Add template for Nehemiah. --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index a271dd57c1d5..42a5ddf38d4e 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -10,10 +10,11 @@ * +---------------------+----------+---------------------------------+ * | Marketing name | Codename | longhaul version / features. | * +---------------------+----------+---------------------------------+ - * | Samuel/CyrixIII | C5A | v1 : multipliers only | + * | Samuel/CyrixIII | C5A | v1 : multipliers only | * | Samuel2/C3 | C3E/C5B | v1 : multiplier only | - * | Ezra | C5C | v2 : multipliers & voltage | - * | Ezra-T | C5M/C5N | v3 : multipliers, voltage & FSB | + * | Ezra | C5C | v2 : multipliers & voltage | + * | Ezra-T | C5M | v3 : multipliers, voltage & FSB | + * | Nehemiah | C5N | v3 : multipliers, voltage & FSB | * +---------------------+----------+---------------------------------+ * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* @@ -345,10 +346,12 @@ static int longhaul_target (struct cpufreq_policy *policy, static int longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; + char *cpuname=NULL; int ret; switch (c->x86_model) { - case 6: /* VIA C3 Samuel C5A */ + case 6: + cpuname = "C3 'Samuel' [C5A]"; longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); @@ -357,11 +360,13 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) case 7: /* C5B / C5C */ switch (c->x86_mask) { case 0: + cpuname = "C3 'Samuel 2' [C5B]"; longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); break; case 1 ... 15: + cpuname = "C3 'Ezra' [C5C]"; longhaul_version=2; memcpy (clock_ratio, longhaul2_clock_ratio, sizeof(longhaul2_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); @@ -369,16 +374,26 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) } break; - case 8: /* C5M/C5N */ + case 8: + cpuname = "C3 'Ezra-T [C5M]"; longhaul_version=3; numscales=32; memcpy (clock_ratio, longhaul3_clock_ratio, sizeof(longhaul3_clock_ratio)); memcpy (eblcr_table, c5m_eblcr, sizeof(c5m_eblcr)); break; + /* + case 9: + cpuname = "C3 'Nehemiah' [C5N]"; + longhaul_version=3; + numscales=32; + */ + default: + cpuname = "Unknown"; + break; } - printk (KERN_INFO PFX "VIA CPU detected. Longhaul version %d supported\n", - longhaul_version); + printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", + cpuname, longhaul_version); if ((longhaul_version==2 || longhaul_version==3) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); -- cgit v1.2.3 From cd48bc4afd2e7db2ec04b3174076b5bc091b116e Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 4 Sep 2003 22:38:49 -0700 Subject: [PATCH] New version of jfsutils needed A recent change to the 2.6.0 kernel has changed the behavior of opening a block device with the O_EXCL flag. This can cause fsck.jfs to fail to replay the journal when a file system is mounted read-only. The JFS utilities have been fixed, and it is recommended that any users of JFS update the utilities to version 1.1.3. --- Documentation/Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Changes b/Documentation/Changes index 5ce920c736c7..f26c7c282164 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -54,7 +54,7 @@ o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version o module-init-tools 0.9.9 # depmod -V o e2fsprogs 1.29 # tune2fs -o jfsutils 1.0.14 # fsck.jfs -V +o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs o xfsprogs 2.1.0 # xfs_db -V o pcmcia-cs 3.1.21 # cardmgr -V -- cgit v1.2.3 From 0d0823fcacb6c9b20ad7ce3d6354c671f1baaebe Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Sep 2003 17:46:42 +0100 Subject: [AGPGART] Remove unneeded string from AMD64 GART driver. --- drivers/char/agp/amd64-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index e351e2966e35..8ae550973d4e 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -370,7 +370,7 @@ static int __init agp_amd64_probe(struct pci_dev *pdev, struct agp_bridge_data *bridge; u8 rev_id; u8 cap_ptr; - char *revstring=" "; + char *revstring=NULL; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) -- cgit v1.2.3 From 5ca838e10f7ba096cbea8f0bd2f29a11e4116570 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Sep 2003 22:47:15 +0100 Subject: [AGPGART] Fix up missing brackets on defines. --- drivers/char/agp/agp.h | 2 +- drivers/char/agp/amd64-agp.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 2a4b9e0dc363..ee679cbdf6d2 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -302,7 +302,7 @@ struct agp_bridge_data { #define AMD64_GARTAPERTUREBASE 0x94 #define AMD64_GARTTABLEBASE 0x98 #define AMD64_GARTCACHECTL 0x9c -#define AMD64_GARTEN 1<<0 +#define AMD64_GARTEN (1<<0) /* ALi registers */ #define ALI_AGPCTRL 0xb8 diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 8ae550973d4e..f60cb63720d8 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -26,13 +26,13 @@ #define GPTE_COHERENT 2 /* Aperture control register bits. */ -#define GARTEN 1<<0 -#define DISGARTCPU 1<<4 -#define DISGARTIO 1<<5 +#define GARTEN (1<<0) +#define DISGARTCPU (1<<4) +#define DISGARTIO (1<<5) /* GART cache control register bits. */ -#define INVGART 1<<0 -#define GARTPTEERR 1<<1 +#define INVGART (1<<0) +#define GARTPTEERR (1<<1) static int nr_garts; static struct pci_dev * hammers[MAX_HAMMER_GARTS]; -- cgit v1.2.3